ShowTable of Contents
Part 1 Introduction
The benefits of builders
Builders are the core technology at the heart of WebSphere Portlet Factory, and they provide three key benefits to developers using WebSphere Portlet Factory:
Easy-to-Use Wizard-Like Interface
Builders provide a nice wizard-like user interface for developing applications, and offer user-friendly features such as drop-down lists that eliminate the need to type in code. Unlike many wizards, builders can be used iteratively through the entire development process, you can always go back and change input values to update the application.
A single builder can automatically generate a whole set of code and metadata for implementing a particular design pattern or piece of functionality. For example, the Data View Portlet builder generates all the code, pages, and metadata for an entire portlet application that displays the results of a database query or a web service call.
Customization and variability
Builders are part of the profiling functionality of WebSphere Portlet Factory. This profiling can be used in a number of ways.
- To create multiple variants of an application from a single source model (for example, a variation for each business partner, with different look and functionality for each).
- To support customization and personalization in a portal. WebSphere Portlet Factory makes it easy to expose customization values. These values are then available to a user in the Edit and the Configure portlet screens.
- To make new high-level builders. You can expose all the functionality of a model as a new builder, using the profiling capability to indicate what the inputs of the new builder are.
The first two benefits of builders, simple UI and automation, together make WebSphere Portlet Factory a powerful RAD tool. The third benefit gives WebSphere Portlet Factory unique and powerful capabilities not available in other frameworks.
Any custom builders that you make are first-class WebSphere Portlet Factory builders and can participate in all the benefits of builders listed above, including the ability to be invoked by other (newer) builders. So when you create new builders, you're extending the power of the WebSphere Portlet Factory.
The WebSphere Portlet Factory framework for making builders
WebSphere Portlet Factory provides a rich framework for creating custom builders, including these features:
- Support for automatically generating rich, consistent user interfaces based on simple XML descriptions.
- Comprehensive and easy-to-use APIs for implementing a builder's regeneration functionality, with the ability to modify elements directly or to invoke any other builders.
- Support for custom dynamic builder user interfaces using the Coordinator interface.
- A set of helper classes to aid in implementing complex builder functionality, such as linked Java objects, that need access to arbitrary indirect reference values. This kind of functionality is typically needed when making new data access builders that provide access to complex back end systems.
- Support for model-based builders, where you can encapsulate all the functionality of a model in a builder.
This tutorial, in conjunction with the Builder Skeleton tool, is intended to provide you with a quick introduction to making builders, and we hope that it gets you hooked on making your own builders. As you will see, the Builder Skeleton tool automates the work of generating all the pieces you need when making a new builder.
When to make a new custom builder
You might consider making a new custom builder for any of the following reasons:
- To automate a task that occurs frequently. If the same set of three or four builders appears in a number of your models, consider consolidating these tasks into a single custom builder.
- To enforce a particular development standard. For example, you might want to enforce a standard that all imported HTML use the Make URLs Absolute and Import on each generation options of the Imported Page builder, and require that they reference a common style sheet. You could do this by making a simple builder that implements this restricted variant of the Imported Page builder.
- To support a new type of data integration. For example, if you have some sort of special back end data access technology, you could make a builder to expose it, to make it easy to access your data and use it with all the other builders, such as Data Page builder.
There are many different things you may want to do with custom builders. Builders can be generic and horizontal, such as the Insert HTML builder in the tutorial below, or they can be specific to a particular technology, company, or industry.
Builder architecture components
There are three main components that make up a builder in the system. The first two are required, and the third is optional.
BuilderDef XML File
The BuilderDef is an XML file that defines the builder and its user interface. All the BuilderDefs for a system are found in the WEB-INF/builders folder of the WebSphere Portlet Factory project. The BuilderDef specifies the name and description of the builder, the builder's Java class name, the builder help, and more. A BuilderDef also describes the builder inputs and their user interface, so that a rich, consistent UI can be automatically generated when the builder is used in WebSphere Portlet Factory Designer. Each builder input is defined with an InputDefinition element. InputDefinitions can inherit from any other InputDefinition (using the base attribute), and WebSphere Portlet Factory comes with a rich set of core InputDefinitions. These base InputDefinitions include things like file pickers, pickers for actions in a WebApp, and a page location picker that lets you pick pages and tags on pages. To introduce a new builder into the system, you simply add the new BuilderDef file under the WEB-INF/builders folder. The system will automatically discover the new builder and make it available.
Builder Java Class
This is a Java class that is called during regeneration of a model. This class can add or modify WebApp elements. WebApp is the name of the structure created by the builders in a model, and it is an abstraction for all the elements that can make up a web application, including pages, variables, schemas, methods, and events.
The builder class implements one of the builder regeneration interfaces (for example, WebAppBuilder or WebAppControlBuilder). It has a doBuilderCall method that is called whenever a model containing your builder is regenerated. The doBuilderCall method can introspect, create, and modify elements in the WebApp object that is being generated. To do this, the builder can call methods on the WebApp object directly, or it can invoke any other builders in the system using the provided callable builder classes. This ability to invoke other builders makes it easy to create successively higher level builders.
The following sequence shows, in simplified form, how builders are invoked during model regeneration, when a WebApp is constructed from a Model XML file.
Regeneration is done in two different contexts: from WebSphere Portlet Factory Designer during model editing, and on the server when a model is first executed.
- The builder's regeneration class is looked up from the BuilderDef and a builder object is instantiated.
- The builder's "doBuilderCall" method is invoked, passing an argument containing all the builder inputs captured in WebSphere Portlet Factory Designer.
- From their doBuilderCall method, builders can introspect, create, and modify any parts of the generated WebApp. They can also invoke any other builders. The builder code uses the builder inputs to control the details of what it does, such as the names of the objects it creates.
Optional Coordinator Java Class
A coordinator is a Java class that can be used to implement a custom dynamic user interface for the builder. For example, you can use a coordinator when you want to present a selectable list of choices that is obtained by calling into some library. Or you might have one checkbox input that controls the visibility of other inputs. The coordinator class is only used in WebSphere Portlet Factory Designer when a builder call editor is open.
Part 2 About the Builder Skeleton tool
The Builder Skeleton tool is a builder that provides a quick, automated starting point for making new builders. It generates the basic code you need when creating builders. It presents a simple user interface for specifying the information about a builder and then generates all the necessary files.
Now, to get past any possible confusion about the fact that Builder Skeleton is itself a builder, remember that all builders generate application code and metadata. Builder Skeleton is just a builder that happens to generate code and metadata for a new builder. The difference between it and other WebSphere Portlet Factory builders is that Builder Skeleton provides no WebApp functionality at all; instead, it is used only in WebSphere Portlet Factory Designer to generate the files for a new builder.
Builder Skeleton generates all the files for a new builder, including the BuilderDef file, the builder Java class, and (optionally) the coordinator Java class. Here are some details about what is generated for each of these:
- In the BuilderDef file, Builder Skeleton fills in all the required information, such as name and description of the builder, the builder's Java class name, the builder help filename, and more. It also fills in the initial set of builder inputs, so the builder can be immediately used in WebSphere Portlet Factory Designer.
- In the builder Java class, code is generated that implements the appropriate interface for the specified style of builder. The generated builder class also has an inner Constants class containing definitions of all the builder input names. This means that you do not need to worry about mistyping input names. These constants are available in other generated Java classes such as the coordinator. The generated code for doBuilderRegen also includes local variables that are initialized to the values of each of the builder inputs.
- In the Java class, the generated code has an inner InputDefinitions class with member variables for each of your builder inputs. See the generated sample code for examples.
All the Java files generated by Builder Skeleton are placed under the
folder, for easy Java editing in the WebApp project in your IDE.
Builder Skeleton is not a complete editor of builder files - it provides quick get you started functionality, but the generated files will need further editing to implement the real functionality you want. Once you edit a generated file, Builder Skeleton will avoid overwriting the file. It does this by keeping a timestamp for each generated file in the builder inputs of the model. If an existing file doesn't match the saved timestamp or if there is no saved timestamp for a file, it displays a warning, and won't overwrite the file. To force the file to be rewritten by Builder Skeleton, simply delete the file and regenerate the model.
Builder types supported by Builder Skeleton builder
Builder Skeleton builder supports creating four types of builder:
Basic WebApp Builder
This is the basic WebApp builder interface. The generated builder class has a 'doBuilderCall' method you can edit to implement your desired functionality.
Page Control (WebAppControlBuilder)
This is used for builders that put JSP or HTML on a page at a specified location. The page location is passed as an argument to the 'doBuilderCall' method.
This is used to create a builder that is based on a model. To do this, you have to first make a model, and profile-enable all the inputs that you want to expose in your new builder.
Model-Based Wizard Builder
This is used to create a new model wizard based on a model. The new model wizard is based on the same underlying technology as builders. As a result, the Builder Skeleton can help you to create a new model wizard in addition to creating a builder.
Part 3 Creating a custom insert HTML builder
Follow these steps to create a new Insert HTML builder. When finished, this new builder will let you specify a page location and an HTML file to be inserted at that location. The builder will import the file, and insert it at the specified location on the page. It could be used, for example, to insert commonly used HTML fragments (such as a legal notice) on a set of pages.
For this tutorial, you will need to have a WebSphere Portlet Factory WebApp project to work in. For debugging builders, it's very helpful to have a console window for the IDE so you can see output from System.out.println calls. To do this, use the -debug and -consolelog flags when starting your IDE.
Creating the builder
- Start WebSphere Portlet Factory Designer and open the WebSphere Portlet Factory project you want to use. Make sure you can run models successfully.
- . Add the Tutorials And Samples > Builders feature set to the project.
- Right-click on the project and select Properties.
- Click WebSphere Portlet Factory Project Properties > Feature info from the navigation pane on the left.
- Add the Tutorials And Samples > Builders feature set to the project. If the feature set has already been added to the project, you may cancel the operation. Otherwise, click OK.
- Open the NewBuilderWizard model in the models/samples/tutorials/builders folder. This model is part of the Tutorials And Samples > Builders feature set that you added to the project. The model is used as a container for the Builder Skeleton builder; you will not run this model on the application server.
An error will appear in the Task view when you open the NewBuilderWizard model. This error is by design, notifying you that required builder call inputs are empty. You will supply values for these inputs in the upcoming steps, and this will clear the error.
- Double-click the Builder Skeleton builder call in the Outline view to open its editor. Click the Reset all inputs to defaults button in the builder call editor to reinitialize everything to defaults. In the builder call editor, enter the following inputs:
- . Builder Type: Page control builder (We will use this because the Insert HTML builder will have a page location input to insert content.)
- . Builder ID: com.bowstreet.test.InsertHTMLBuilder
- Readable Name: Insert HTML (This is the name that will be shown in the builder picker.)
- Description: Imports an HTML or JSP file and inserts it at the specified page location.
- Builder Inputs:
1. There will be two default inputs, Name and PageLocation, that were automatically created for you because this is a page control builder.
2. For the Name input, set the Input Type to Builder name (required) and check the Is Required box.
3. After the two default inputs add a third input with File as the Name, File (servable content) as the Input Type, and HTML File as the Prompt. Check the Is Required checkbox.
- Click the OK button to save the builder call and close the builder call editor.
- Save your model. Click on the Application Tree view and look for the "Comments" section marked InsertHTML files for the lines that indicate that two files have been generated under the WebApp folder. In the WebApp tree, expand the Comments folder abd click the InsertHTMLBuilder files comment to see the comment showing the names of the generated files:
* Builder class: \work\source\com\bowstreet\test\InsertHTMLBuilder.java
* BuilderDef: \builders\com\bowstreet\test\InsertHTMLBuilder.bdef
The IDE will add the generated Java files to your project.
- Find the Java file for InsertHTMLBuilder in the com.bowstreet.test package of the project source, and open it for editing.
- Note the generated code that defines all the builder input names and the doBuilderCall method that gets the Name and File builder inputs. Also notice the sample code in doBuilderCall. This code uses the Text class to invoke the Text builder. This builder places "Hello builder world!" text on the page.
The basic Insert HTML builder has now been created and compiled, and you can test it using the sample ("Hello builder world") functionality before adding the real functionality we want. For this part, we will use additional files that are part of the Tutorials And Samples – Builders feature set. The BuilderTutorialTest model has a simple page containing a SPAN tag named "footer" at the bottom; "footer.html" is the file to be imported and inserted at that location.
- Open the BuilderTutorialTest model in the models/samples/tutorials/builders folder. It contains two simple pages with navigation links between the pages. Each page has a SPAN tag with a "footer" name attribute.
- Click the Add Builder Call icon located in the upper right-hand corner of the Outline view to summon the Builder Picker. Your new builder should now be in the Custom Builders category.
- Select the Insert HTML builder from the right-hand side of the Builder Picker, and click OK.
- In the builder call editor, enter the following inputs:
1. Name: footer
2. Page Location:
1. Page: AllPages
2. Tag: footer
3. HTML File: /samples/tutorials/builders/footer.html
4. Click OK to save the builder call.
- In the Application Tree view, click page1 in Pages folder. Notice the generated HTML in the Application Tree view that says "Hello builder world!"
- Make sure your application server is running.
- Run the model. "Hello builder world!" should appear on both pages of the application. Your new builder is operational, and now you can start to edit its functionality.
- To see how your builder can generate code (JSP code in this case), go to the doBuilderCall method in the InsertHTMLBuilder.java file. This method contains sample code that programmatically invokes the Text builder. To generate some JSP that will place the current date/time on a page, replace the line containing "Hello builder world" with this code:
textBuilder.setText("<BR>Time: <%= new java.util.Date().toString() %><BR>");
- Save/compile the modified Java file, and regenerate the BuilderTutorialTest model again in WebSphere Portlet Factory Designer. Notice the new generated JSP in the Application Tree view. Run the model, and you should now see the current date/time displayed in the page footer.
- Now edit the doBuilderCall code again to implement the real functionality for importing and inserting an HTML page. To do this, you will programmatically invoke the Imported Page and Inserted Page builders, using callable builder classes from the com.bowstreet.test.webapp.api package. These builder classes have set methods corresponding to the builder inputs. Remove the four lines of code that use the Text class, and type in or paste this code instead:
ImportedPage imp = new ImportedPage(builderCall, genContext);imp.setName(name); imp.setURL(file); imp.invokeBuilder();
InsertedPage ins = new InsertedPage(builderCall, genContext);ins.setPageLocation(pageLocation); ins.setPage(name);ins.invokeBuilder();
This code invokes the ImportedPage builder to create a page whose name is taken from the Name input, importing a file whose URL is from the File input. It then invokes the InsertedPage builder, using the PageLocation input and specifying the page name from the Name input again.
# Save/compile the modified Java, and regenerate the BuilderTutorialTest model in WebSphere Portlet Factory Designer. In the Application Tree view, you should see a new "footer" page that has been created by the Insert HTML builder.
# Run the model. You should see the new footer page inserted at the bottom of both pages.
Congratulations! You have made a new custom builder. Hopefully, with Builder Skeleton taking care of the initial mechanics of making builders, you will feel ready to go further with your own builders.
In this example, we did not need to open the BuilderDef file for manual editing. However, in most cases you will need to do more editing of this file, for example if you want to have a drop-down list input. Refer to the WebSphere Portlet Factory documentation for complete information about BuilderDef files.
Suggested next steps
This tutorial has illustrated the mechanics of creating a simple custom builder. Here are some suggested next steps and places to look for more information on making builders:
- Try out the Builder Skeleton option for creating a coordinator class. This class is invoked when your builder is open for editing in WebSphere Portlet Factory Designer, and this is where you can implement custom code for a more dynamic builder user interface. For example, if you want to show/hide some inputs based on another input, you can do it in the coordinator.
- See the Overview of builder architecture section of the WebSphere Portlet Factory > Working with Portlet Factory section of Help in the WebSphere Portlet Factory Designer for information on BuilderDef files and builder classes.
- Try out some of the other options in Builder Skeleton. These options include Generate Helper and creating a model-based builder. See the help for Builder Skeleton builder for information.
- To get some ideas for the types of things builders can do, look through the builders that come with WebSphere Portlet Factory to see what inputs they expose and the functionality they generate.
- Look at the sample builders that are part of the Tutorials and Samples - Builders feature set. The sample models for these are in WEB-INF/models/samples/builders, the sample bdef files are in WEB-INF/builders/com/bowstreet/samples/builders, and the Java code is in WEB-INF/work/source/com/bowstreet/samples/builders.
- Post any questions or problems on the WebSphere Portlet Factory developerWorks forum.
- To share builders with other developers using WebSphere Portlet Factory, use the File Export command, and select the option for WebSphere Portlet Factory Archive to create a ZIP file containing your builder files. The files can then be installed into a project using File > Import.