Overview: Builder architecture
In this topic ...
Choosing Builder Base Classes and Interfaces
Related Topics ...
A builder is a discrete bundle of functionality in the construction of a WebApp. Of the Builders that are supplied in the Factory, some are primitive and do very simple things, like adding a page to the WebApp, or putting a button on a Page. Others are complex, and can constructing an entire form along with the Java code required to move data between the form and a variable.
There are three critical pieces to a Builder.
- Builder Definition File (bdef) -- This XML file defines the Builder for the Factory to know both how to invoke it and how to display instances of it to the developer who wants to use the Builder. Among other things, it defines what the inputs are to this Builder. In our example, the Builder has only two inputs, the name of the Builder and the directory which contains the HTML files that it is going to create links to.
- Builder Class -- This is a Java class which performs the automation task. It is run at Generate time, and it is expected to make some changes to the WebApp.
- Coordinator Class (Optional) -- This Java class is run when a developer is editing an instance of the Builder -- a BuilderCall. The coordinator can modify the Builder's user interface on-the-fly to hide or show input fields, change the list of choices in a ComboBox, etc. In our example, the Coordinator is just used to set the initial value of one of the inputs to a value that is calculated. (If the initial value were something static, we could just set it in the Builder Definition file.)
Choosing Builder Base Classes and Interfaces
Depending on how your builder acts on the WebApp, you will need to extend or implement a specific base class or interface for your generation class and specify an appropriate GenHandler class in the builder definition. The following table lists the three ways of implementing a builder:
Keep these implementations in mind when creating the builder definition and generation class for your own builder.
The list below enumerates the fully-qualified class names for each of the classes/interfaces mentioned in the table above. Click on the links to display the JavaDoc for each.
- com.bowstreet.builders.webapp.foundation.WebAppControlBuilder
- com.bowstreet.builders.webapp.foundation.WebAppBuilder
- com.bowstreet.builders.webapp.foundation.BaseWebAppControlBuilder
Builder Definition Files
The builder definition file is an XML file that resides in or below the WEB-INF/builders directory. The actual directory in which the builder definition resides corresponds to the package name of the generation class. For example, if the fully-qualified class name for the generation class is: com.acme.sitebuilders.AutomatedPagesBuilder, the builder definition would the following path and file name:
WEB-INF/builders/com/acme/sitebuilders/AutomatedPagesBuilder.xml
Builder Definition Structure
The builder definition file has the following structure:
<BuilderDef>
<ReadableName />
<GenHandlerClassName />
<GenerationPasses />
<HelpFile />
<RequiredFactoryVersion />
<Description />
<Domains>
<Domain />
...
</Domains
<CoordinatorClassName />
<BuilderData>
<BuilderDataEntry />
...
</BuilderData>
<InputDefinitions>
<InputDefinition />
...
</InputDefinitions>
<Editors>
<Editor />
</Editors>
</BuilderDef>
The following table describes each of the elements in the builder definition:
Element Name Description BuilderDef Besides containing the rest of the elements in the builder definition, the BuilderDef element has an "id" attribute that you set to the file path and name of the builder definition file. The path is relative from the Factory's WEB-INF/builders directory and directory names are separated using dots "." as in Java package names. For example, <BuilderDef id="com.bowstreet.builders.webapp.ButtonBuilder">
ReadableName Set the value of this element to be the name of the builder. This name appears in the Designer's builder palette.
For example: <ReadableName>Button</ReadableName>
The WebSphere Portlet Factory does not support the use of bi-directional characters in Builder names. This might cause problems in languages in which these types of characters are commonly used, such as traditional Chinese, simplified Chinese, Korean, and Japanese.
GenHandlerClassName Enter com.bowstreet.builders.webapp.foundation.WebAppGenHandler for builders that do not use a Page Location input. Enter com.bowstreet.builders.webapp.foundation.WebAppControlGenHandler for builders that do use a Page Location input.
HelpFile Enable the designer to launch a help file for this builder by setting this element's value to the path and filename for the help file. Paths are relative from the Factory's servable content root directory. For example, <HelpFile>factory/product_documentation/builders/button.htm</HelpFile>
Store the help files for builders that you create somewhere under the Factory's servable content root. The HelpFile value for a builder will be similiar to:
<HelpFile>acme/builders/automated_site.htm</HelpFile>
where acme/builders is the directory in which the help file, automated_site.htm resides.
RequiredFactoryVersion Set this element value to correspond to the core Factory engine / runtime version as displayed in the server startup message (to the console of the server and/or stdou). For example,
<RequiredFactoryVersion>x.y.z</RequiredFactoryVersion>
Do not set this value to the displayable product version as shown in the Designer. In some cases version value will represent versions of the plugins, not of the Factory.
Description Set this element value to the text that you want displayed in the builder call editor for this builder. For example, <Description>
Add a button to one or more pages in the model .
</Description>
Domains Contains Domain elements. Domain All builders specify at least one domain: <Domain>WebApp</Domain>. CoordinatorClassName Optional. If you have created a coordinator class to add logic to the builder call editor for the builder, set this element value to the coordinator class' fully-qualified class name. For example, <CoordinatorClassName>
com.bowstreet.builders.webapp.ServiceCallBuilderCoordinator
</CoordinatorClassName>
BuilderData Contains BuilerDataEntry elements. BuilderDataEntry Set the value of the "name" attribute for this element to "BuilderClassName" and the value for this element to the builder's generation class' fully-qualified name. For example, <BuilderDataEntry name="BuilderClassName">
com.bowstreet.builders.webapp.ButtonBuilder
</BuilderDataEntry>
InputDefinitions Contains InputDefinition elements. InputDefinition Contains elements that define the input type, associated widgets to edit the input, the prompt to display for the input, and help text to display as a caption for the input. For example, <InputDefinition name="ActionType"
base="com.bowstreet.core.Base.Select">
<Editor>
<Argument name="listData">form,link,script</Argument>
</Editor>
<Prompt>Action Type</Prompt>
<HelpText>
Determines whether clicking this button submits a form,
links to another page, or executes a script.
</HelpText>
</InputDefinition>
Defining input definitions is fully described in "Creating Builder Defintions."
Input Widgets
The input definitions specified in the builder definition determine the input value type (String, boolean, etc.) and the user interface component that the Factory servlet generates for your builder's Builder Call Editor.
To streamline the creation of input definitions, the Factory includes a Base.bdef and WebAppBase.bdef builder definitions. Each of these base builder definitions contains predefined input definitions that include specialized editors. These specialized input definitions are called "widgets" and combine the input value type (String, boolean, etc.) with a specific editor. For example, the IndirectComboBox widget returns a String value determined by a choice in a combo box or by the Reference Chooser, allowing the user to specify a value from a form input, variable, or method for the input value.
In your builder definition, we can simply refer to the input definition in the Base.bdef file to incorporate the specified widget into the Builder Call Editor for your builder:
<InputDefinition name="Color" base="com.bowstreet.core.Base.Select">
<Prompt>Choose a Color</Prompt>
<Editor>
<Argument name="listData">Blue, Red, Green</Argument>
</Editor>
</InputDefinition>
This input definition prompts the Builder Call Editor to display a list box with Blue, Red, Green available as choices and a prompt of, "Choose a Color." The input value is named, "Color."
For more information about specifying input definitions, see "Creating Builder Definitions."
Generation Class
The generation class implements all the logic to be executed by the builder during generation. In this class, we can automate the addition of elements to the Web application, add builders to the model, that operate on one or more pages in the model, and perform any other logic needed during generation.
Depending on how your builder affects the WebApp, your generation class will either implement the WebAppBuilder interface or the WebAppControlBuilder interface. See the builder implementation table in this topic for more details.
A builder can affect the Web application in two ways:
- It can add elements to the Web application. Elements that can be added to the Web application include:
- Linked Objects
- Linked Models
- Imported Pages
- Event Declarations and Handlers
- Variables
- It can modify elements in the Web application. Some builders modify pages, adding or modifying controls on those pages. Builders can also modify other elements in the Web application such as adding to the structure of a variable, adding actions to an action list, etc.
For a definitive list of builders that operate on the structure of the Web application, see the builders listed as WebApp builders in the Builder Palette. For the list of builders that can modify the elements in a Web application, see the builders listed as JSP builders in the Builder Palette.
Add Elements to the Web Application
The Factory servlet passes the Web application structure to the builder call with the webApp argument.
To add elements to the WebApp structure:
In the doBuilderCall() method, add calls similar to the following to add the desired elements to the Web application:
//Add linked object to the Web application
webApp.addLinkedObjectVariable("runtimeLO",
"com.acme.methods.SiteBuilderMethods");
//Add an ActionList to the Web application
ActionList initPages = webApp.addActionList("initPages");
// Add a counter variable.
Variable counter = webApp.addVariable(varName, Variable.TYPE_INTEGER);
counter.setValue(new Integer(0));
For more information about adding elements to the Web application, see "Creating Builder Generation Behavior."
Add Elements to Pages in the Web Application
We can add or modify elements on the pages in the model by calling the individual builder APIs. Individual builder APIs are in the com.bowstreet.builders.webapp.api package. Each builder has the invokeBuilder() method in common, which prompts the builder to execute on the specified pages in the model.
The following code examples show how to create a new builder call, set the inputs on that builder call, and then use the invokeBuilder() method to execute the builder call:
// Insert the a page at the location passed into this builder.
InsertedPage connector = new InsertedPage(builderCall, genContext);
connector.setPageLocation(builderInputs.getString("PageLocation",null));
connector.setPage(pageName);
connector.invokeBuilder();
// Put a button on our page which just re-submits the current page.
Button b = new Button(builderCall, genContext);
b.setPageLocation("Page " + pageName + " NameSearch increment");
b.setLabel("Increment");
b.setActionType("form");
b.invokeBuilder();
// Put a text builder to display a variable value.
Text txt = new Text(builderCall, genContext);
txt.setPageLocation("Page " + pageName + " NameSearch display");
txt.setText("${Variables/" + varName + "}");
txt.invokeBuilder();
As shown above, you will often need to get the inputs to your builder call to perform specific generation actions.
To get the builder call inputs:
The builderInputs object is an XML structure containing the names and values of the builder call inputs. To get individual input values, use the appropriate get() method in the BuilderInputs API. For example,
String pageLocation = builderInputs.getString("PageLocation", null);
boolean modelAction = builderInputs.getBoolean("ModelAction", null);
IXml xmlInput = builderInputs.getXml("CustomerList", null);
Object xmlInput = builderInputs.getObject("PurchaseOrder", null);
For more information about adding elements to pages in the Web application, see "Creating Builder Generation Behavior."
Runtime Logic Classes
If we need code to execute at runtime, in your generation class, we can add a Linked Java Object to the WebApp that implements the functionality we need. Some common things we need to do at runtime are:
- Interact with the file system
- Interact with an LDAP directory service or JDBC data source
Coordinator Class
If we need to implement any sort of dynamic behavior for a builder call editor, create a coordinator class for your builder. The coordinator can set input definitions as visible or not, add input definitions, and modify the display of the builder call editor when an input value changes. See "Implementing a Coordinator," for more information.