The WidgetServer-Framework is a OpenSource-Framework for the development of Client-Server applications. It is primarily developed by the Munic based company: C1 SetCon. The following chapters will offer a short introduction the the technological aspects and features of the framework.
The WidgetServer Framework implements a multi-channel approach, where it is possible (for example)to present both a HTML Interface and a Swing-client GUI to the users. A side-effect of this concept is the the programming and configuration of the Servlet-API is not visible to the developer.
The entry point, the servlet, establishes a connection to the servlet API. The GUI defintion is established per XML, whereas the API while providing a complete componet class structure is decoupled from the specific implementations. The individual HTML component sources are delivered in template files. The "Half-Object" channel utilizes the Swing API directly. Swing is also the smallest common denominator within the Framework, this may be encountered in the use of the common implemenations, common patterns, and models (like the TableModel and TreeModel).
One basic difference to the "classic" web application development in the 'markup' channel is to realize that every client-server interaction performs only a partial refresh; specifically, only the portions of the HTML-DOM tree that has been changed through either the user or the server are sent and updated. This is referred to as 'partial-rendering' in WidgetServer (whereas full-rendering is also possible) and it is this feature that allows one to design and implement GUIs in the same manner als one would standard desktop applications. The individual components of the visible application will be changed without a complete rebuild of the website.
This technique is more commonly known as AJAX and is accomplished through the use of IFrames and JavaScript. Although, WidgetServer does not use the XMLHttpRequest object, the same objectives are acheived in both the the development and usability.
Throughout this tutorial, parrallels and references to more classic web application development with Servlets and JSPs will be referred to allowing a point of reference for web developers to get started with WidgetServer.
The first project
The 'WidgetServerBlank' project which is included in the distribution is a complete eclipse project ready to be imported. It includes all relevant launch targets as well. It is a good point to start.
The graphic user interface definition of a WidgetServer application is defined primarily in XML. It is also possible (and sometimes necessary) to define GUI elements by using the provided Java API. The WidgerServer Java API is flexible and allows for extensive manipulations.
A component tree is built per XML, which is possible to manipulate on the server at runtime and send updates to the client side.
In addition to the documentation, it is often quite helpful to view the elements within the delivered GUI-Builder, check
the element in the Widgets View in Eclipse, or directly in the source code of WidgetServer. Specifically the class:
de.ug2t.unifiedGui.UnApplFactSAXHandler
and all the inner-classes (example:
de.ug2t.unifiedGui.UnXMLTAGinpField
for the
<inputField>
-Element - a simple Textfeld), which defined in xml will be referenced in the runtime.
<include>
A Include mechanism through the tag
<include file="..." />
establishes a basis for a modularized and therefore easier to maintain more complex GUI structures.
<application>
The XML root element for an application is
<application>
. As a direct child element of the application tag, one may define an initalization class that will be configured and
initalized after the parsing of the xml data.
<appInit class="..." />
).
This element is comparable to the ServletContextListener of the Servlet API (javax.servlet.ServletContextListener). However there is one minor difference; WidgetServer may be so configured so that by every new HTTP-Session the GUI defintions are newly loaded. Thereby, newly initalizing a specific initalization class for every user session, and not just once upon server start.
So called "Pre-" and "Post" function classes may be defined and summoned before and after (respectively) every
request.(
<preFunction class="..." />
,
<postFunction class="..." />
).
These classes are similar to the ServletFilter classes (javax.servlet.Filter), except that they are separately defined and not called in nested heirarchies; but rather one after the other in the order that they are defined in the XML file.
It is also possible to define an application menu bar(
<menu>
) . However, one must also define atleast one
<page>
- application page.
<page>
A
<page>
represents an entire application window. Within the "Markup" channel, is this the entire display area of the
web-browser. The name of the
<page>
sets the value in the title bar of the browser window.
<dialog>
A dialog can be opened and closed, independantly of the underlying page. They may also me moved on the screen. Further optional parameters control the modalarity, title bar, dimensions, and decorations.
There are many different types of dialogs: non-modal and modal dialogs, system dialogs in three formats ('alert' for a similar message with an OK button, 'message'--really a confirmation dialog-- for dialogs with Yes/No buttons and 'input' dialogs for simple dialogs designed to obtain user input.
Non-modal dialogs may be opened/closed through the partial rendering mechanism, but may have one disadvantage (depending upon needs) of having the underlying components still active. The user will still be able to interact with these components and activate their listeners. Modal dialogs, on the other hand, lock the underlying page requiring an entire page load.
The so-called 'System Dialogs' are defined through JavaScript in the HTML channel and are therefore dependant upon the client environment--the browser version and langauage. They require a complete rebuild when opened or closed. The 'alert' dialog opens a JavaScript alert() popup. The 'message' type opens a confirm() dialog and the 'input' opens a JavaScript input() popup.
<form>
and Layout
The next and probably most used tag within a page or dialog is
<form>
. This establishes a container for other components. A
<form>
contains a predefined layout (within the HTML channel usually a GridBagLayout) and is per default scrollable.
This structure has less in common with the HTML-Form as with a JPanel from the Swing-API.
Along with the very flexable but very complex to use and render GridBagLayout (from the Swing-API fame), there exists
further possibilities components within a
<form>
to position: nested boxes. The boxes of WidgetServer are a special type of container, that order their child elements
in pre-defined ways. A
<hbox>
orders its components horizontally, while a
<vbox>
orders its elemenets vertically.
The WidgetServer Framework delivers a rich set of predefined GUI components. There is the well-known text input
component:
<inputField>
, Text-Area
<textBox>
, Checkbox
<checkBox>
, Radiobutton
<radio>
, Listbox
<listBox>
, Combobox
<comboBox>
and Button
<button>
. Futher components are
<label>
(for text output with an Icon and special fonts) or Border
<border>
(a
<form>
with a border and title). More complex GUI components with comprehensive API-support are tabls
<table>
and Trees
<tree>
are also integral parts of the component catalogue. Further supported components are
<line>
(a horizontal line for the structuring of the GUI),
<toolTip>
,
<icon>
,
<item>
(element in a list, menu, or combobox). As further supporting the components there is a list of tags dedicated to
specific functions like layout aids:
<position>
,
<fixedSize>
,
<filler>
and lots more for various diverse purposes may be used.
As a good reference on the various diverse possibilities refer to the "Builder" and especially the "HelloWorld" applications found in the WidgetServer release structure. The HelloWorld application has less to do with the traditional 'HelloWorld' that we all known and more with a showcase of the GUI components.
Every component is backed by a Java class that saves the state of the component. The markup channel also has a further Renderer class that offers dedicated (HTML) presentation possiblities through component individual templates. Typically, a default template set is offered for every browser engine type (which may be extended); otherwise, the renderer will end with an error message.
WidgetServer delivers a standard template kit, containing 4 versions: one for Internet Explorer, one for Mozilla, one for Opera and one for Safari (Chrome) based browsers. The recognitions of exactly which template kit to use is based upon the the request-header information of the client.
When the basic components do not fill all the needs, it is possible to combine components in new ways and define your
own components for reuse. These reusable structures are refered to as "Plug-Ins" and are used in the XML-GUI
defintions per the
<plugin use="..." />
tag. The Plugins are defined in the WidgetServer configuration files. Important files are the parfile.xml (defining
the standard delivered plugins) and extensions.xml (for newly created plugins).
A plugin needs, just like standard components, a Java class that encapsules the plugin functionality. Such functionalty as, initalization the GUI or saving the state of the plugin in the components at runtime. The Plugin class can also be used for the central controlling of events; thereby combining the functions of a controller and model from the MVC pattern. Therefore, it may be helpful to consider a separation of the logic into further classes for more complex plugins. The plugin class must extend a specific WidgetServer class (de.ug2t.unifiedGui.plugins.PlBasicComponentAggregat) and will be per reflection initalized. Furthermore, the initalization method initPlugin() may be overloaded to perform initalization directly after being created.
Attention: Do not reference the component tree during the initalization. At this point in time within the initPlugin(), is the plugin not yet in the component tree integrated.
public class MyPlugIn extends PlBasicComponentAggregat {
@Override
public void initPlugin(UnComponent plugInComponent, Object xmlAttributes, String rootDir) {
super.initPlugin(plugInComponent, xmlAttributes, rootDir);
// initialize the plugins GUI
...
}
}
The first component (node) in the plugin definition becomes the root component of the plugin, often a
<form>
-component, which will contain all the other components. The rest of the attributes of the tag are seldom used:
xmlAttributes - a instance of org.xml.sax.Attributes - contains the attributes of the
<plugin>
-elements from the XML-GUI definition data and may also be extended for further parameters. 'rootDir' is set to the
rootDir from the Plugin definition file (parfile.xml or extensions.xml). In most cases, is this value not set and is
therefore null.
Folgendes Beispiel zeigt die Registrierung eines (internationalisierten) Calendar-Plug-Ins in parfile.xml.
Example 1. Beispiel für eine Plug-In-Definition
<Cluster name='Calendar'>
<Parameter name='xmlConf' value='Std_plugins/Calendar/xml_gui/Calendar.xml' />
<Parameter name='staticXmlConf' value='Std_plugins/Calendar/xml_gui/CalendarStatics.xml' />
<Parameter name='initClass' value='de.ug2t.unifiedGui.plugins.calendar.Calendar' />
<Parameter name='textFile' value='Std_plugins/Calendar/xml_gui/i18n_{$LANG}.xml' />
<Parameter name='defaultTextFile' value='Std_plugins/Calendar/xml_gui/i18n_EN.xml' />
</Cluster>
...
<Cluster name="plugins">
<Parameter name="Calendar" value="Calendar" />
...
</Cluster>
The GUI portion of a Plugin is also written in XML, similar to the rest of the application
The parameter "xmlconf" (from above)indicates the path to the GUI defintion file, realive to [app-name]/start/ .
However, there is one limitation to the registration of global object names (see Section 3.2.3.3, “Problem by
multiple use Plugins -
<pluginLocal>
”). staticXmlConf
Static initalizations that really are only once for all instances of a particular plugin (for instance: the defintion and registration of pictures) are found in a further, optional XML file: "staticXmlFile" contains the path to this file, also relative to [app-name]/start/.
initClass
This parameter defines the fully qualified class name of the above describe plugin class. This class be created at runtime through reflection.
textFile
This parameter is the path to a text file containing language variations for internationalizations (see section on “Internationalisierung”). Also a relative path to [app-name]/start/.
The pattern [$LANG} will be replaced with the language code of the actual request at runtime. If the file being searched for does not exist, then the value from the default text file will be used.
The following chapter will touch upon some important API elements of the WidgetServer Framework.
A central API component is the class de.ug2t.kernel.KeTreeNode. The component tree consits of KeTreeElements and KeTreeNodes, whereby all GUI componets extend UnComponent are therefore KeTreeNodes.
Figure 2. Class diagram of component base classes

Every component that can react to user actions, may contain one or more event-listeners. Examples of such are: Buttons, Links, Menu-Items, but may also be other Read-Only components like: Listboxes or trees.
Listeners are declared in the XML GUI defintion files through the tag:
<srvListener>-
Although it may be possible to define many listeners for one component, it is a better practice to define one
listener that will delgate the actual work to the appropriate controller (Application controller or plugin specific).
Otherwise, the active code is spread across too many levels and becomes harder to maintain.
Example 2. XML-Referenz eines Listeners
<button value="%#LANG_ContextEditor:Buttons:Add">
<fixedSize width="50" height="23" />
<srvListener class="com.c1setcon.gui.contexteditor.AddDialogListener" />
</button>
Every user interation triggers a small HTTP-Request, which will summon the associated Listener. There are no different events based upon the type of components, only the standarized Java Interface which every listener implements. The listener will receive the triggering compoment as method parameter.
Example 3. Listener-Interface (de.ug2t.unifiedGui.interfaces.IUnGuiEventListener)
package de.ug2t.unifiedGui.interfaces;
import de.ug2t.unifiedGui.UnComponent;
public interface IUnGuiEventListener
{
public abstract void execListener(UnComponent eventSender)
throws Exception;
}
The capability to react to specific user actions (like: mouse movements or key presses) is provided by the
'Event-Channels' (
<eventChannel>
), that may be registered to the components. An instance (of the now familiar) of a ServerListener needs to be
entered into the EventChannel as a child element to provide the functionality. A "CLICK" event is a standard event
for a button, but here it is also possible to define a 'click' event for a label. A further example of the usage of
the EventChannel is the need to react within a textfield to a confirmation event; namely the "ENTER" key should send
the data to the server. Since there is no standard event for textfield for this, an event ala
<eventChannel>
-must be defined. The following will show an example for a "KEYACTION" EventChannel within a textfield.
Example 4. Definition of a EventChannel
<input size="30" len="256" register="RgContextEditorAddDialogNameField" submit="true">
<eventChannel name="EnterKeyChannel" submit="true" type="KEYACTION" key="ENTER">
<srvListener class="com.setcon.gui.contexteditor.AddDialogListener" />
</eventChannel>
</input>
The saving of data over many request is offered in the WidgetServer Framework through its own object registry per user session and is matched with key-value pairs.
Classic web application normally offers the HTTP-Session for such use. But due to the Multi-channel needs, WidgetServer offers its own implementation for the saving of data across multiple requests.
Many XML-Elements support the attribute 'register="..."'. Thereby, each component is capable of storing the value in the global registry during the parsing of the xml data. Later, at any point in time, may one, either per XML or programmatically, obtain the stored value with the registered name.
The attribute 'object="..."' of the XML Element allows a direct binding of a stored object in the registry direct on the given XML element. A practival example is the reuse of stored pictures and fonts.
<font name="Arial" size="12" style="bold" orphan="true" register="RggenericBoldFont" />
A Label within another area of the GUI definitions can then reference the name "RggenericBoldFont" (registered in the above example) and reused.
<label value="Bold Text">
<font object="RggenericBoldFont" />
</label>
A further practical example of transfering the String values for use out of the global object registry follows:
<label value="#RgLoggedInUser" />
This example shows the referencing of a text value that had been programmatically stored in the registry. The pound symbol "#" as the first character is an indicator for the framework the the following text is a key in the registry.
The Java class "de.ug2t.kernel.KeRegisteredObject" offers many static helper methods to work with the registry.
There are also other possibilities and special cases supported, like saving to a special context.
Since a plugin may potentially be used multiple times in a page, it should logically not be stored in the global
registry. Such a case will result in a "duplicate object registration" error, since another plugin object is already
stored within the same context. Rather, it is better to use a plugin local way, hence the tag:
<pluginLocal name="..." />
, which will save the surrounding XML element with the given name within the plugin context. CAUTION: Not all the XML
elements support this tag.
<tableLoader>
and
<treeLoader>
are common examples (non-GUI components). However, a standard workaround to do this in the correspondig loader
classes (for example in the initPlugin()-Method) programmatically and bind on the respective component
<table>
and
<tree>
.
A table can be a very complex GUI construct, just like in any GUI framework. Luckily, WidgetServer utilizes a well-known standard API from the Java world: the Swing API. The definition of the table contents is accomplished through the javax.swing.table.TableModel. Here ends the contact point with the Swing API, atleast for the "Markup" channel, and picks up with WidgetServer constructs. Figure 3. Overview of the Table-API

The connection of a table, a renderer, and its model are bound together in the GUI definition files through a TableLoader. Or, more specifically, an instance of a de.ug2t.unifiedGui.loader.UnTableLoader. Example 5. <table> and then a <tableLoader>
<table selectable="true" submit="true" factoryDesc="borderlessAndPlainHeaderTable">
...
<tableLoader register="RgsomeEditorContextVersionTableLoader"
rendererClass="com.setcon.gui.someEditor.versiontable.VersionTableRenderer" />
</table>
The above example, shows a tableLoader that is registered in the registry, so that later the TableModel may be loaded
in code. The creation and referencing is always done in code; for-example, in an initalization method of a plugin or
activating per listener call. This requires that the "register" attribute of the
<tableLoader>
-Tag is used, so that the tableLoader may be found. Example Loading of a TableModels
javax.swing.table.TableModel tableModel = createTableModel();
UnTableLoader loader = (UnTableLoader) KeRegisteredObject.getObjByName("RgsomeEditorContextVersionTableLoader");
loader.connectModel(tableModel);
loader.load();
Problematical is it only for tables that occur more than once in the GUI, especially within the same page, and are visible. In this case, the multiple registration would overwrite each other. The only possibility would be to also programmatically bind the tableLoader.
Example 7. Programmatically Create and Load the TableLoader
// create table model:
javax.swing.table.TableModel tableModel = getModel();
// initialize table:
if (tableModel != null) {
if (matrixLoader == null) {
IUnTable table = (IUnTable) getForm().getSubNode("Matrix");
// create loader, attach to table:
matrixLoader = new UnTableLoader(tableModel, table, new
CompatibilityMatrixRenderer(this));
} else {
matrixLoader.connectModel(tableModel);
matrixLoader.load();
}
}
Cautions: There is also the same cautionary measures with registrations as elsewhere in the framework. -The tag (see “Cautions By Multiple Reuse of Plugins" <pluginLocal> ”) is not supported in the <tableLoader> -Tag.
It is most often not practicle to simply call the 'toString()' method to transfer the TableModel contents to the GUI elements. Especially by complex tables where the individual cells should react to user interactions, dedicated models and also table cell renders are required to create these cells.
TableRenders implement the interface 'de.ug2t.unifiedGui.cellRenderer.IUnTableItemRenderer' and allow the returning a dedicated GUI component for every element of the TableModel. This can be accomplished directly through code using the WidgetServer API or in the XML GUI file defintions, which will be read during the parsing of the files and generated.
Example 8. Generation of the GUI Components through the Runtime Parsing of a GUI Definition (IUnTableItemRenderer)
public Object getRenderWidget(Object xToRender, int xRow, int xCol, IUnTable xTable) {
...
String fragmentPath = "subGUIs/EditorCalendar/xml_gui/fragments/outputCell.xml";
de.ug2t.unifiedGui.interfaces.IUnApplication application = xTable.getAppl();
UnApplicationFactory applFactory = new UnApplicationFactory("", application.getComponentFactory(), false);
applFactory.useNonStaticHandler(true);
return applFactory.produceWidgetsFromFile(application.getApplType(), fragmentPath, application);
}
The path to the given GUI definition file is listen, like in most cases, realive to the 'root Directory' for the given application. (see Section 3.3.6, “web.xml - Connection to the Servlet-API”).
No less complex as the table is the Tree GUI element. The Tree component also uses elements from the Java Swing API; namely, the TreeModel and the TreeNode-API.
The rendering of the individual nodes also utilizes the WidgerServer implemented rendering API.
Figure 4. Overview of the Tree API 3.2.5.1. UnTreeViewLoader

A Tree can not be filled without a real javax.swing.tree.TreeModel instance. The referencing of a TreeLoader which will load a tree follows a similar method as a <table> but rather uses a <treeLoader> -Tag within the <tree> -Elements. Example 9. <tree> and <treeLoader> in a XML-GUI-definition file
<tree name="-">
...
<treeViewLoader register="RgsomeEditorTreeLoader"
rendererClass="com.setcon.gui.someEditor.contexttree.TreeNodeRenderer" />
</tree>
The registration of a TreeLoaders follows the same guidelines and restrictions as for TableLoaders (see above).
The TreeRenderer works similar to a TableRenderer, only in this case is object type to be rendered an instance of javax.swing.tree.TreeNode.
The renderes need to implement the interface 'de.ug2t.unifiedGui.cellRenderer.IUnTreeItemRenderer' and allow a specific individual rendering of special GUI components for each and every TreeNode. Through the API method of the javax.swing.tree.TreeNode one may verify what type of node (leaf, root, or branch) needs to be rendered.
Example 10. Generation of a GUI Component by Reading of a GUI Definition File (IUnTreeItemRenerer)
public Object getRenderWidget(Object xToRender, boolean xSelected, IUnTreeView xTree) {
...
String fragmentPath = null;
if (contextTreeNode.isLeaf()) {
fragmentPath = "plugins/someEditor/xml_gui/contexttree/leaf.xml";
} else if (contextTreeNode.isRoot()) {
fragmentPath = "plugins/someEditor/xml_gui/contexttree/root.xml";
} else {
fragmentPath = "plugins/someEditor/xml_gui/contexttree/node.xml";
}
if (fragmentPath != null) {
de.ug2t.unifiedGui.interfaces.IUnApplication application = xTree.getAppl();
UnApplicationFactory applFactory = new UnApplicationFactory("", application.getComponentFactory(), false);
applFactory.useNonStaticHandler(true);
return applFactory.produceWidgetsFromFile(application.getApplType(), fragmentPath, application);
} else {
return new UnTreeNode(xToRender.toString());
}
}
Once again, the given path is a relative path to the root directory of the application.(see Sectionon “web.xml - Connection to the Servlet-API”).
This class offers many static helper methods, like:
public static String deRef(String value);
public static String deRef(String value, String defaultValue);
These methods lead to variable substituions based primarily upon the XML Attributes set.
Strings that begin with a "#" character, will be swapped out with a value from the global object registry (see section on “KeRegisteredObject - Global Object-Registry”). If an object is found in the registry, the string value is thereby returned by calling the toString() method.
Strings that being with a "%" character, refer to data stored in the WidgetServer XML configuration data format (see Section on “Konfiguration”). Such files consist of three further string values matches separated with a ":" character. These tokens describe the path to the value and the key to look up said value. Each level (token) is interpreted and sent further through the tool to build the appropriate level and also sent through KeTools so that the following is possible::
String value = KeTools.deRef("%#LANG_TypeEditor:labels:#RgButtonName");
The token "LANG_TypeEditor" must have already been stored in the object registry, which indicates a path from a WidgetServer XML configuration file (like and Internationalization file). The token "labels" indicates the cluster found within that file; while "RgButtonName" indicates a value from the object registry.
The format of the WidgetServer configuration files is always the same: XML. The main groups are called "Cluster" and these contain many child elements called "Parameter". The "Parameter" elements contain further key-value pairs.
Figure 5. XML-Schema of the WidgetServer Configuration Files

The following shows an extract from the environment.xml, which contains global values for the WidgetServer Framework:
<?xml version='1.0' encoding='ISO-8859-1'?>
<Parameter_List>
<Cluster name='MY_LANGUAGE_LOCALE_MAPPING'>
<Parameter name='DEFAULT' value='en' />
</Cluster>
<Cluster name='MY_LANGUAGE'>
<Parameter name='en' value='xml_gui\i18n_en.xml' />
<Parameter name='DEFAULT' value='xml_gui\i18n_en.xml' />
</Cluster>
<Cluster name='runtime'>
<Parameter name='ENCODING' value='UTF-8' />
</Cluster>
...
</Parameter_List>
The class de.ug2t.kernel.KeEnvironment contains many static helper method to access the configuration data stored in XML.
KeEnvironment.getParameter(String filename, String cluster, String parameter)
The filename indicates the file to search through, cluster indicates the group level, and parameter is the final key match of the parameter chain. There are more helper methods (like default value setting and so on), but the most of time these are not needed.
The following is a simple example showing the accessing of a value from the above example.
String runtimeEncoding = (String) KeEnvironment.getParameter("environment.xml", "runtime", "ENCODING");
Directly referencing configuration parameters in the XML GUI definition files is performed by the framework recognizing the "%" character. At runtime, the framework will check all XML attributes to see if one begins with the percent (%) symbol. In such a situations, the KeEnvironment class will trigger this replacement. The following example shows a similar replacement, but this time in an XML GUI file.
<label value="%environment.xml:runtime:ENCODING />
The colon (:) in the string value (after the percent symbol) separates the separate parameters (a token) within the KeEnvironment.getParameter() call.
The exact same XML schema and the same extracting syntax are also used for the internationalization file. For further details see the section on "Configuration".
The following topics will discuss the most important points of the central configuration files.
The file environment.xml contains all the important runtime configuration parameters for the WidgetServer Framework. It can also be extended for your own configuration parameters. The most important parameters are listed in the following section.
Table 3. Important Parameters in environment.xml
ENCODING
WidgetServer Encoding, used by the XML-Parser,to read the XML files (Configuration files, GUI definitions, ect.)
MY_LANGUAGE DEFAULT
A path variable to the default internationalization file that should be used when no other matching language is found.
Parallel to the 'DEFAULT' language setting, one may also set the language specific files for every desired langaugage that is to be recognized in the HTTP-Request. Listed below is the DEFAULT language (when no match is found) and a language defintion for the English language.
<Cluster name='MY_LANGUAGE'>
<Parameter name='en' value='xml_gui\i18n_en.xml' />
<Parameter name='DEFAULT' value='xml_gui\i18n_en.xml' />
</Cluster>
A language file (Internationalization file) has the same XML-Schema and organizational structure as previously discussed, broken down into "Cluster" and "Parameter" elements.
The files parfile.xml and extension.xml contains the configuration details for every GUI component and Plugin in the Markup channel. These files thereby define, in a way, the entire XML syntax of the GUI defintions.
Example 11. Defining a GUI Component
<Cluster name='comboBox'>
<Parameter name='MuTemplate' value='html_comboBox.templ' />
<Parameter name='MuComponentClass' value='de.ug2t.channel.markup.generic.MuGenericComboBox' />
<Parameter name='HoServerClass' value='de.ug2t.channel.ho.server.generic.HoSrvGenericComboBox' />
</Cluster>
The name of the
<Cluster>
-Tags correspond with an XML Tag that may be used in the GUI file; like,
<comboBox ... />
indicates to the framework to combine the given component (a combobox) into the component tree.
The
<Parameter>
from the above example, whose name begins with "Mu", stands for the "MarkUp" channel; while, the "Ho" prefix stands
for the "HalfObject" (Swing)channel.
There must be at-least one parameter there, which will describe for the actual channel the basis Java class needed. For the "MarkUp" channel is this the "MuComponentClass" and for the Swing channel the "HoServerClass".
The "MarkUp" channel also needs the template parameter name called "MuTemplate", which will state the necessary renderer. The renderer will not be configured here; rather, it is tightly bound to given component class. The component class defines the necessary values and configurations needed. Hence the need for alternative templates to be in the same format as the standard WidgetServer Templates--for the proper configuration.
This is also one of the most common situations for the customization of the framework: a new component that uses the same standard classses but a new, optimized template for a different look.
Example 12. Defining a new GUI Component while Reusing the Standard Component Classes
<Cluster name="enhComboBox">
<Parameter name="MuTemplate" value="html_enhancedComboBox.templ" />
<Parameter name="MuComponentClass" value="de.ug2t.channel.markup.generic.MuGenericComboBox" />
<Parameter name="HoServerClass" value="de.ug2t.channel.ho.server.generic.HoSrvGenericComboBox" />
</Cluster>
Through a
<include>
-tag may such a GUI data be imported into the actual GUI structure.
Example 13. extensions.xml
<Parameter_List>
<include file="xml_parameter/genericPlugIns.xml" />
<Cluster name="plugins">
<include file="xml_parameter/genericPlugInDefinitions.xml" />
</Cluster>
</Parameter_List>
Example 14. xml_parameter/genericPlugIns.xml
<Parameter_List>
<Cluster name="simpleLabel">
<Parameter name="HoServerClass" value="de.ug2t.channel.ho.server.generic.HoSrvGenericLabel" />
<Parameter name="MuComponentClass" value="de.ug2t.channel.markup.generic.MuGenericLabel" />
<Parameter name="MuTemplate" value="html_simpleText.templ" />
</Cluster>
...
<Cluster name="Permissions">
<Parameter name="xmlConf" value="plugins/Security/Permissions/xml_gui/Permissions.xml" />
<Parameter name="staticXmlConf" value="plugins/Security/Permissions/xml_gui/PermissionsStatics.xml" />
<Parameter name="initClass" value="com.setcon.gui.security.permissions.PermissionsPlugIn" />
<Parameter name="textFile" value="plugins/Security/Permissions/xml_gui/i18n_{$LANG}.xml" />
<Parameter name="defaultTextFile" value="plugins/Security/Permissions/xml_gui/i18n_en.xml" />
</Cluster>
<include file="xml_parameter/otherPlugIns.xml" />
</Parameter_List>
Example 15. xml_parameter/genericPlugInDefinitions.xml
<option>
<Parameter name="simpleLabel" value="simpleLabel" />
...
<Parameter name="Permissions" value="Permissions" />
<include file="xml_parameter/blbbPlugInDefinitions.xml" />
</option>
The
<option>
-Tag in the last example is a "NoOp" Tag (in this case), that simply servers as a 'wrapper' object to allow the XML
document to have a root node.
The deployment desccriptor from the Servlet API (web.xml) is used to establish the only connection from WidgetServer to the Servlet world. The following shows such a basic deployment descriptor with some basic WidgetServer specific configurations.
Example 16. Configuration of the Deployment Descriptor--web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>basicServlet</servlet-name>
<description></description>
<servlet-class>de.ug2t.unifiedGui.service.UnBasicServlet</servlet-class>
<init-param>
<param-name>rootDir</param-name>
<param-value>{$SERVLETCTX}start</param-value>
<description></description>
</init-param>
<init-param>
<param-name>guiTemplateDescFile</param-name>
<param-value>environment.xml</param-value>
<description></description>
</init-param>
<init-param>
<param-name>guiApplDescFile</param-name>
<param-value>xml_gui/main.xml</param-value>
<description></description>
</init-param>
<init-param>
<param-name>guiFactDescFile</param-name>
<param-value>xml_parameter/parfile.xml</param-value>
<description></description>
</init-param>
<init-param>
<param-name>initClass</param-name>
<param-value>com.setcon.gui.widgetserver.StaticInitializer</param-value>
<description>Initializer class called at the end of the servlet's initialization.</description>
</init-param>
<init-param>
<param-name>rootURL</param-name>
<param-value>[app-name]/start</param-value>
<description></description>
</init-param>
<init-param>
<param-name>fullRender</param-name>
<param-value>false</param-value>
<description></description>
</init-param>
<init-param>
<param-name>TIMEOUT</param-name>
<param-value>14400</param-value>
<description></description>
</init-param>
<init-param>
<param-name>REDIRECT_ON_INVALID_CLIENT</param-name>
<param-value>start/HTML_Pages/client_error.html</param-value>
<description></description>
</init-param>
<init-param>
<param-name>TEST_COOKIE</param-name>
<param-value>TRUE</param-value>
<description></description>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>basicServlet</servlet-name>
<url-pattern>/start</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>basicServlet</servlet-name>
<url-pattern>/start/IFRAME</url-pattern>
</servlet-mapping>
</web-app>
The most important portion is the
<servlet-mapping>
, which identifies not only the rootDirectory of the application, registered to the basicServelt from WidgetServer
(de.ug2t.unifiedGui.service.UnBasicServlet)
<init-param>
but also registers the "IFRAME" used for the Ajax similar actions.
The initalization parameters of the Servlet itself are listed in the following section.
Table 4. Important
<init-param>
-Elements of UnBasicServlet
Parameter-Name Value
rootDir {$SERVLETCTX}start has to be the absolute path to the application ($SERVLETCTX} will be replace with the absolute path of the ServletContext-Root of the files system of the application.
guiTemplateDescFile--environment.xml--is the path to the central runtime configuration file(relative to the rootDir)
guiApplDescFile--xml_gui/main.xml--is the path the the main GUI definition file of the application(relative to the rootDir)
guiFactDescFile--xml_parameter/parfile.xml--is the path to the main GUI configuration file (relative to the rootDir)
initClass--com.setcon.gui.widgetserver.StaticInitializer--is the fully qualified class name of the initalization class that will be summoned during the initalization of the WidgetServer Servlet. This class must implement the interface de.ug2t.kernel.interfaces.IKeExecutable.s
fullRender--false--Indicates that a partial rendering of the web page should be used. A value of 'true' would indicate that the web page should be fully rebuilt with every Request.
rootURL--[app-name]/start--is needed for the Session and Upload handling. This requires that the ServlectContext path and the path to the root of the application are there for the relative paths of the web application to be valid.
The internationalization in the WidgetServer Framework is based upon the "Accept-Language" header of the HTP-Request of the client browser. This normally has the format: Accept-Language: de, en-gb;q=0.8, en;q=0.7 (which pretty much means "I prefer German, also accept British English and other english variations. Refer to the related topic by the W3C for further details). This defines the order of the different languages that the client browser accepts.
WidgetServer offers two different possiblities/areas for the interantionalization: application level and plugin level.
Internally is the value from the Request header's "Accept-Language" assigned to a file, which is defined in the WidgetServer XML configuration format (see Section, “Configuration”). This assignment is done per static calls to the configuration file environment.xml.
<Cluster name='MY_LANGUAGE'>
<Parameter name='en' value='xml_gui\i18n_en.xml' />
<Parameter name='pl' value='xml_gui\i18n_pl.xml' />
<Parameter name='DEFAULT' value='xml_gui\i18n_en.xml' />
</Cluster>
When no value-to-file match exists for the Request-Header value, then the framework will use the DEFAULT value (from the example: xml_gui\i18n_en.xml).
The discovered langauge code (en, pl, or DEFAULT) will be stored in the global registery under the name IUnApplication.MY_LANGUAGE_CODE (value: MY_LANGUAGE_CODE). The path to the file is also stored under the name IUnApplication.MY_LANGUAGE (Value: MY_LANGUAGE).
All of the mentioned files need the same exact structure
<Cluster>
- and its child element
<Parameter>
Otherwise, the summoning code will not receive the appropriate text, but rather a cryptic defintion string.
A Plugin established a reusable compilation of components and may contain its own internationalzation files, independant of the applications internationalization files.
The configuration of these plugin specific internationalization files is defined in the parfile.xml and/or extension.xml configuration files--ie. in the same place that the plugins themselves are defined.
Example 17. Definition of the Internationalization within a Plugin Defintion
<Cluster name="someEditor">
<Parameter name="xmlConf" value="plugins/someEditor/xml_gui/someEditor.xml" />
<Parameter name="staticXmlConf" value="plugins/someEditor/xml_gui/someEditorStatics.xml" />
<Parameter name="initClass" value="com.setcon.gui.someEditor.someEditorPlugIn" />
<Parameter name="textFile" value="plugins/someEditor/xml_gui/i18n_{$LANG}.xml" />
<Parameter name="defaultTextFile" value="plugins/someEditor/xml_gui/i18n_en.xml" />
</Cluster>
The parameter "textFile" defines a path for all the interanationalization files. The pattern {$LANG} will be replaced at runtime with the value from the "Accept-Language" value from the Request-Header to identify the appropriate file. This example shows a setting for the language code "en" the path to "plugins/someEditor/xml_gui/i18n_en.xml" as the default language.
When a search for langauge file does not exist for the given plugin, then the default language file will be used ("defaultTextFile").
The referencing of the values from the internationalization data has its own special syntax, similar to the global referencing which was:
"%#MY_LANGUAGE:ClusterName:ParameterName"
Example 18. Usage of the Internationalization Data Reference
<button name="NewButton" value="%#MY_LANGUAGE:Buttons:New">
...
</button>
The #MY_LANGUAGE will be expanded to the name of the internationalization file; while, 'ClusterName' and 'ParameterName' each refer to a specific level in the file, like in the following example:
<Parameter_List>
...
<Cluster name="Buttons">
<Parameter name="New" value="Create..." />
...
</Cluster>
...
</Parameter_List>
When one would like to use internationalized file data is the syntax a little bit different; namely, %#LANG_PlugInName:ClusterName:ParameterName.
Example 19. Usage of Internationalized data in a Plugin GUI
<label value="%#LANG_Calendar:Month:January" />
<toolTip tip="%#LANG_OtherCalendar:ToolTips:PrevMonthButton" />
#LANG_PlugInName will be expanded to the path to the plugin specific internationalized file that should match the actual language request. 'ClusterName' and 'ParameterName' (2nd and 3rd portion) reference the specific cluster and parameter level within that file. 'PluginName' must correspond to the Plugin name from the defintion file (parameter.xml/extensions.xml)-- specifically the value from the "use" attribute of this file.
<plugIn ... use="<PlugInName>" />
Both text files may also be referenced through code with the KeTools.deRef(String), similar to the other areas in the program.
Example 20. Code Referencing with KeTools.deRef()
newButton.setValue(KeTools.deRef("%#MY_LANGUAGE:Buttons:New"));
monthLabel.setValue(KeTools.deRef("%#LANG_Calendar:Buttons:New"));