The Source for Java Technology Collaboration


Writing JSF Custom Components for Sun IDEs

This page contains information on writing custom JSF components and delivering them as a component library in a complib file for NetBeans Visual Web Pack (VWP) and Sun Java Studio Creator IDEs. Please email comments to EdwinGoei. Thanks for the feedback.

ALERT! As of 2007-03-12, this document needs to be revised with information on current IDE development which is occuring on the NetBeans nbusers and nbdev mailing lists. It is still somewhat useful in that it describes how components can be assembled into a complib file. The original popup calendar sample code in this article has been updated and incorporated into the java.net blueprints project.

This document is directed towards third-party component developers instead of the typical IDE web application developer user. We assume that the developer has a deeper understanding of JavaServer Faces (JSF) and general Java platform development. This information is for Creator version 2 and above including NetBeans 5.5 Visual Web Pack and above.

A set of components can be bundled together into a component library and delivered to an IDE web application developer as a single complib file. A complib file is just a package file much like a war or ear file containing the contents of a component library.

Table of Contents

Overview

This document tries to take a concrete, by-example approach to documentation. We will develop a simple complib containing both JSF components and a converter. However, we also present an overview of the major steps of the process along with links to details. You may want to skip over these details upon a first reading of this document.

Creator uses the standard JavaBeans component architecture to associate property editors, customizers, and other metadata with a component at design-time. A JavaBean component or bean is a reusable software unit that exposes its features such as properties, methods, and events, to tools. Creator expects user-manipulatable objects to be beans. This includes JSF components such as text fields and command buttons as well as JSF converters and validators. It also applies to non-JSF components such as DataProviders. Creator obtains metadata on these beans by using BeanInfo classes and the CreatorDesignTimeApi.

In this document, "design-time" refers to parts of an application that are only used by a tool or integrated development environment (IDE) such as Creator. The word "runtime" refers to parts of an application that are always deployed to a servlet container or application server. Some runtime parts may also be used in a tool at design-time. The following list outlines the major steps for adding third-party components to Creator.

  • Creating the runtime components themselves taking into consideration design-time aspects since some of the code will also be executed at design-time. Components should also be beans and should meet some guidelines before they will work well in Creator. Adapting existing JSF components for use in Creator should also follow these same guidelines. For details, see CreatorComponentRules.

  • Creating the design-time artifacts for the components. The design-time artifacts include JavaBeans BeanInfo classes, property editors, customizers, icons, and other resources as well as classes that are part of the CreatorDesignTimeApi.

  • All the parts: the runtime components, the design-time code, icons, javadoc, source, and a complib manifest need to be assembled into a complib file. For details, see ThresherComplibSpec.

  • The user imports the complib into Creator and uses the components in an application.

Component developers should perform the above steps iteratively until they are satisfied with the results.

Sample Simple Component Library

We will illustrate the major steps of the process by example. We will develop a simple complib containing JSF components and a converter. This new sample is an evolution of the older sample-date complib but has been updated. Currently, it contains a date picker component, a DHTML popup calendar component, and a combined java.sql.Date and java.util.Date converter along with some design-time classes. Eventually, the plan is to add other non-date related components so I have also renamed the complib to make it more generic.

If you are writing your own JSF component or modifying an existing component to work in Creator, the popup calendar is probably the better component to use as a template. It is an example of a more complex component to illustrate how one can add resources such as JavaScript and CSS files to a complib. One of my product responsibilities was to fix problems in the current Creator built-in calendar component. I realized that this component needed to be refactored so I thought I would write a new version of a popup calendar as a real-world example. So I started by doing a survey of existing date-picker and popup calendar type of components on the web and came up with a set of requirements. I think I have come up with an improved prototype which can be the basis of a new product-quality popup calendar. Feel free to modify it and extend it to fit your needs. For screenshots, see this blog entry.

You can obtain the following files using the Creator auto update center (Tools->Update, I think):

This file will be pla

The following files are obsolete and will be removed in the near future:

Ideally a tool should support any JSF component and this is also Creator's long-term goal. However, often times this requirement conflicts with ease-of-use for the user. Creator was originally targeted for ease-of-use and so full generic JSF support is being delayed for future releases. For example, Creator allows the user to drag and drop components onto a design canvas. In order to support this, the components themselves must follow a more restrictive set of rules to work well in Creator. See CreatorComponentRules for more information. This information is also useful when modifying an existing component to work well in Creator. In this sample, however, we develop components from scratch.

Parts of a Component Library

Creating a component library involves creating various parts and then packaging these parts into a single complib file. A complib may contain several parts:

  • Runtime jars contain classes and metadata that are deployed to a server at runtime as part of the application. Runtime jars are also used at design-time.

  • Design-time jars contain classes and metadata that are used by the IDE itself and are not deployed at runtime.

  • Javadoc zip files that contain javadoc used by Creator users. Not deployed.

  • Source files that contain Java code used by Creator users. Not deployed.

  • Help information that is used by Creator users. Not deployed. (Not currently implemented 2006-01.)

  • A complib manifest which points to a configuration XML file to specify the complib package contents. For example, META-INF/MANIFEST.MF and complib-config.xml.

Creator components do not necessarily have to be JavaServer Faces (JSF) components but they all have to be beans. For example, DataProvider-s are beans but they are not JSF components. Going back to JSF, a "JSF component" is a subclass of UIComponent and is sometimes referred to as a "visual component" because it typically has code to render markup for display in a user agent. For visual components, Creator displays the rendered markup in the designer at design-time. This leads to the use of the term "non-visual component" for other types of beans.

Creating a runtime jar is a good place to start. The runtime artifacts are typically packaged in one or more jar files. In our sample, we have a JSF converter which is a non-visual component. Typically non-visual components can be implemented by hand. However, visual components are typically more complex. A visual component can be further divided into three kinds of Java classes plus some metadata:

  • Metadata: sample-simple.tld (tag library descriptor)
  • The UIComponent itself: DatePicker.java, PopupCalendar.java
  • Its Renderer: DatePickerRenderer.java, PopupCalendarRenderer.java
  • Its tag handler: DatePickerTag.java, PopupCalendarTag.java

Writing a visual JSF component typically involves creating several classes and a config file many of which are boilerplate and can be derived from the same set of metadata. Instead of manually trying to keep the different parts of a component in sync, one approach is to keep a single set of metadata and provide a code generator to derive the boilerplate classes and config file. This is the approach we will take here. Our sample has faces-config.xml and sun-faces-config.xml files containing metadata which is used as an input into a code generator to produce both runtime and design-time artifacts. Please note that the code generator is optional, if you have problems running the code generator for your own components, you can view the output of the generator for this sample to figure out how to manually write your own code.

Some of the design-time artifacts are typically packaged in a design-time jar and can also be further divided:

  • Design-time classes: PopupCalendarBeanInfo.java describes the PopupCalendar bean. SqlUtilDateConverterBeanInfo describes the SqlUtilDateConverter bean. PopupCalendarDesignInfo.java supports dynamic design-time behavior.
  • Other code: such as PropertyEditor-s: YearAlignPropertyEditor.java
  • Other resources: PNG icon for DatePicker

Other optional files such as javadoc and source code may also be packaged in zip files and allow the IDE to provide javadoc and source during development. Finally, a catalog containing all of the previously described parts of a complib allows the IDE to determine its contents.

Creating Runtime Jar(s)

Let's start by creating a runtime jar which contains JSF components. The converter can be manually implemented as a bean without any properties. For visual components, there are typically three associated kinds of runtime classes: the UIComponent class itself, the tag handler class, and the renderer. Much of the UIComponent code is boilerplate and can be automatically generated. Similarly, the tag handler follows a boilerplate pattern and can also be automatically generated. In fact, no special component code should be in the tag handler since current versions of Creator do not execute tag handlers at design-time. Of the three, the renderer is what gives the component its unique character and is thus typically hand-written. The TLD can also be automatically generated.

Running the Code Generator

A JSF runtime requires a faces-config.xml file to determine the types of components, converters, validators, and renderers for an application. The schema for this file is extensible and Creator extends this schema to allow additional metadata which can be used as input to a code generator. Typically, this extended metadata file is called sun-faces-config.xml and follows the SunFacesConfigDtd schema. Since faces-config.xml is required by a JSF runtime, only the minimal metadata required for runtime is included in that file. The sun-faces-config.xml contains all other information.

Let's look at the sample faces-config.xml file. Notice it has minimal information about the date picker component and its renderer. When creating a new component, add entries to this file first. Next, look at the the sun-faces-config.xml file. Notice this file contains the component's description, tag-name, taglib-uri, base-component-type and instance-name as well as all its properties. Also, each property contains its own description and other metadata such as its display name, type, JavaBeans property editor, and category in the property inspector.

The metadata in the sun-faces-config.xml file will be used to generate

  • Component base classes containing concrete properties and value bindings. For example: DatePickerBase.java

  • Taglib handler classes containing code to collect JSP attributes and set their values on properties in component classes. For example: DatePickerTag.java.

  • Taglib TLD file describes to the JSP compiler in a container how to process the tags in a JSP page. For example: sample-simple.tld.

  • JavaBeans BeanInfo base classes contain metadata on a component. For example: DatePickerBeanInfoBase.java.

See the "gen-all" target in the ant build.xml file for details on running the Creator code generator with the sun-faces-config.xml as input. Warning: the code generator interface is not stable and is likely to change in the future.

Runtime: Final Steps

After running the code generator, we need to manually write the actual renderer and component classes themselves. For details, see the code in the following files:

  • Renderer class: DatePickerRenderer.java

  • Component class: DatePicker.java which extends DatePickerBase

Finally collect all the runtime classes, resources, and faces-config.xml file and create the runtime jar. See the "jar-rt" ant target.

Design-time Jar(s)

The next major step is to create a design-time jar. As mentioned previously, the design-time jar contains BeanInfo classes and other items that are not deployed to a container but are only used by a tool. The "gen-beaninfo" target, which the "gen-all" target mentioned in the previous section runs, also generates BeanInfo base classes. These base classes need to be extended to create BeanInfo classes. Warning: if you forget to extend the BeanInfo base class, your component will not work correctly because the JavaBeans Introspector will return a runtime synthesized BeanInfo instead. Creator uses BeanInfo classes as the exclusive source of static metadata about components. See DatePickerBeanInfo.java for more information. Note how an icon can be associated with the component by adding an image file and how PropertyDescriptor-s can be manipulated.

Another kind of item contained in a design-time jar are DesignInfo classes. DesignInfo classes provide dynamic behavior rather than static information about a component. In our sample, DatePickerDesignInfo.java shows how a property can be changed at design-time when a new instance of a date picker is added to a page. The sample also shows how a DateUtilConverter can be linked to a DatePicker using the CreatorDesignTimeApi. This API extends the standard JavaBeans API and adds a rich set of new features to manipulate components and properties at design-time and provides the IDE with context menu items, customizers, and extended property editors.

Other items that are typically placed a design-time jar are PropertyEditor-s, category descriptors, and localization resource bundles. For example, in the DatePickerBeanInfo, the DatePicker "yearAlign" property is associated with the "com.example.util.YearAlignPropertyEditor" which is also included in the design-time jar. For details, see the "jar-dt" target in the sample build.xml file.

Other Items

There are other optional items that are useful to Creator users and may be included in a complib.

  • Javadoc: see the "javadoc" and "complib" ant targets
  • Source files: see the "complib" ant target which shows how a zip file of source can be included
  • Help: eventually help files will also be supported

Assembling the Complib File

The final steps are to assemble the complib file. First, create a jar manifest file containing a pointer to an XML config file. In this example, complib-config.xml contains all metadata about the complib itself. See ThresherComplibSpec for more information on the schema for this file. In our example, the conf/complib-config.xml file contains a pointer to a Java property ResourceBundle for internationalization and among other things explicity declares component classes within palette categories. Note: it also uses filter expressions which are replaced by the ant copy task. Finally, the complib file itself is created with the jar ant task. See the "complib" target for details.

Test your component library as follows:

  • Open the Component Library Manager dialog by selecting Tools->Component Library Manager from the menu bar or selecting "Manage Component Libraries" from a palette category context menu
  • Click on the "Import..." button in the dialog which will open another dialog
  • Browse to your complib file and import it
  • Add a component from the newly imported complib to test your component

Importing a complib will cause Creator to expand the package and add new components into the user palette. You may need to open a palette category to see the new components. The expanded complib will be copied to a location under the current user directory, ~/.Creator/complibs/. (This is not a stable location.) Test a component by adding a component to the design surface. The first time this happens, the IDE will copy the unpacked complib into the project. Also a new Library Reference in the project will be created. You can see the added Library Definitions and References by selecting the Properties context menu item of the main project's node in the Project navigator.

Notes and Tips

  • Whenever a new version of a component library is imported into Creator, it is stored under the Creator userdir and does not affect any existing projects that may use older versions. This is because each project has its own copy of a complib. A complib is first copied to a project when a component in it is first used in a project. See more details here.
  • When developing a component iteratively, it is often useful to change some code, generate a new complib, import it into Creator, and test the new code within an existing project. To force the old project complib to be overwritten, you can add a component from the newly imported complib displayed in the palette to a page in the project and then undo the add. This will cause the new complib to overwrite the older complib in the project even when both complibs have the same identifier (uri, version pair). Creator uses timestamps to implement this behavior.
  • To completely remove a complib from a project, as opposed to the userdir, and without replacing it with a different version, see this link. A better user interface for this feature is planned.
  • Until a more functional Java standard design-time API is agreed upon (JSR-273), third parties can use the Creator Design-Time API that allows a richer design-time experience. See CreatorDesignTimeApi for more information.
  • A command line property can be set to specify the initial complib import browse directory. For example, on Windows you can open a dos prompt and execute: C:\Sun\Creator\bin\runide.exe -J-Dtoolbox.importStartDir=/cygwin/home/edwingo/tmp.
  • New in Creator 2 is the ability to auto-install a complib by placing it in a special directory $RAVE_INSTALL_HOME/complibs_to_install/. Upon the next restart of the tool, the complibs will automatically be installed into the user's palette.
  • If you develop a visual JSF component using a similar procedure as the sample above and adding your component to a project makes it appear in the Application Outline but not in the designer and no exceptions are shown in the log, check that you have a BeanInfo class that extends the generated BeanInfoBase class.
  • If you see the following warning message in the IDE log file, it can be safely ignored. The latest version of the sample should not have this problem. Ignore message: "You are trying to access file: complib-config.xml from the default package...".
  • Existing generic JSF components such as myfaces and ourfaces that have not been modified to work with Creator will not work without additional effort. However, it may be possible to get some components to work by adding additional design-time code and in other cases by also modifying component runtime code. They can then be packaged into a complib file. See CreatorComponentRules for guidelines.

Problems with this Sample

The following lists known problems with the sample code. Problems will be addressed in a future version of the code. Please report any problems to EdwinGoei.

  • Date properties "year", "month", and "day" do not always update properly in the property inspector. Click on the property to see it update. These are also read-only properties and can currently only be accessed using Java code getter methods.

Open Issues

  • The code generator command line interface is not stable and is likely to change in the future. This means that basing your component library build on the sample ant file may not work in future versions of Creator. The generated code itself should be more stable, however.

  • The sample-simple complib uses non-portable but useful internal PropertyEditor-s. These may not be available in a future release. The workaround is to write your own PropertyEditor-s.

  • Some PropertyEditor-s in sample-simple rely on a NetBeans API to alert the user when a String cannot be parsed. This may be a Creator bug. I will try to resolve this issue. The workaround is either to use the NetBeans API as done in the sample or to catch exceptions within the PropertyEditor itself. The latter solution unfortunately does not inform the user of a problem.

References

Troubleshooting

  • If you try to add a new visual component from the palette to a page in the IDE and expect something to appear on the page and instead only see the component in the Outline view, then this often means that the associated custom BeanInfo class of the component cannot be instantiated. In reality, a default BeanInfo class is created internally by introspection, but the default is not very useful. One way to check this is to write a unit test that instantiates the BeanInfo classes of your components.

Updates

  • 2007-04-12 Added #TroubleshootingAnchor section.
  • 2007-03-12 Updated Intro with newer info on VWP.
  • 2007-03-03 Moved Updates section to bottom.
  • 2006-06-12 Added note that this document needs to be revised.
  • 2006-03-23 Added tips on copies of complibs in projects and how to remove them.
  • 2006-03-10 Added #DownloadAnchor
  • 2006-03-06 Draft 2.4: sample-simple-2.2.1.complib: fixed bugs with popupCalendar when embedded in a table.
  • 2006-03-02 Draft 2.3 Added more complex popupCalendar component to complib version 2.2 to illustrate capabilities such as adding JavaScript and CSS.
  • 2006-02-08 Draft 2.2.2 Clarified visual vs non-visual components
  • 2006-02-06 Draft 2.2 Minor updates
  • 2006-02-03 Draft 2.1 in progress
  • 2006-02-02 First Creator 2 (Thresher) draft.
  • 2006-01-30 Started updating documents for Creator 2 (Thresher). Watch this space for more info. Until this update is completed, see the previous version.
  • 2005-07-29 Minor updates.
  • 2005-07-28 Fixed sample-date-2.0 example complib and updated docs.
  • 2005-07-26 Draft based on old Reef version of this document at WritingCustomComponents.
  • 2005-07-26 Created

Topic CustomComponentLibraries . { Edit | Ref-By | Printable | Diffs r21 < r20 < r19 < r18 < r17 | More }
 XML java.net RSS

Revision r21 - 13 Apr 2007 - 01:08:19 - Main.edwingo
Parents: WebHome > SunJavaStudioCreator