C H A P T E R 4 |
Developing Model Components |
This section assumes that you have already read Develop Your First Component found in Chapter 2, Developing Components.
The obvious Model components are the extensible Model components. Extensible Model components are custom implementations of the Model class which are intended for specialization by application developers. The specialization by application developers will usually consist of application developers adding schema information to their application specific Models. The Sun ONE Application Framework Component Library contains a number of extensible Model components, such as QueryModelBase, WebServiceModel, SessionModel, ObjectAdapterModel, and CustomModel.
The ModelComponentInfo interface allows component authors to define additional metadata that is applicable to all Model components.
The ExecutingModelComponentInfo interface allows component authors to define additional metadata that is applicable to all Model components whose component class implements the com.iplanet.jato.model.ExecutingModel interface.
Is it possible to create a non-extensible Model component?
The answer is yes. In fact, whenever application developers create a new Model via the Model wizard, they are in fact extending an extensible Model component and creating an application-specific Model. This new application specific Model is by definition a non-extensible component. Whenever an application developer attempts to fill out a property of type ModelReference, the IDE toolset will invoke a component browser that allows the application developer to choose from a set of existing non-extensible Models. For instance when a application developers specify a DisplayField's Model Reference property, the IDE toolset presents them with a browser that allows them to select a Model.
Is it possible to create one of these non-extensible Models and add it to a library so that it can be distributed? Again, the answer is yes. See the section Developing and Distributing Non-Extensible Model, Command and ContainerView Components below.
A non-extensible Model component is a concrete Model that has been created within the IDE from an extensible Model component. It is no different from an application specific Model, except that is distributed in a JAR file and can be incorporated into multiple applications. The distribution technique is common for non-extensible Models, ContainerViews, and Commands. See the section Developing and Distributing Non-Extensible Model, Command and ContainerView Components
This section describes how to create a new extensible Model component that acts as an adapter to an arbitrary XML document. The adapter pattern is one of the patterns which Sun ONE Application Framework Models are well suited to implement. In this example, the Model component will allow Sun ONE Application Framework Views to access arbitrary XML document data in a Sun ONE Application Framework consistent way. View developers will not need to know anything about the XML internals, or any XML specific APIs. Instead, the View developers will interact with the XML document Model as they would any other Sun ONE Application Framework Model. This hightlights one of the key aspects of Sun ONE Application Framework Model design. Sun ONE Application Framework Models are intended primarily to serve as application resources which are used by Views. For more on the relationship between Sun ONE Application Framework Views and Models see the Sun ONE Application Framework Developer's Guide.
Designing a new extensible Model is generally a non-trivial undertaking. The following example is sophisticated, yet concise enough for this guide. As with any Model, alternative designs are possible. As with any example, further refinement is encouraged for a production quality version. The objective of this section is to familiarize yourself with the mechanics of Sun ONE Application Framework extensible Model implementation.
This example introduces several additional Sun ONE Application Framework component model topics, as follows:
This Model will not be a business delegate. Some models ARE both adapters and business delegates. For example, the Sun ONE Application Framework standard component library's JDBC SQL Query Model is both an adapter and a business delegate because it is responsible for communicating with the enterprise tier.
The XML Document Model will not be responsible for the lifecycle of the XML Document. It will assume that the application has managed to acquire the XML document. The Model does not care how the application acquires the XML document. The Model will rely on the application to place the XML document within a well defined location. The Model will access the XML document from that location, as needed.
There are several benefits to this design decision beyond just making the Model's job simpler. For one, this approach will allow > 1 XML Document Model access to the same XML Document. During the testing of the component you will see how this Document-Model cardinality will benefit application developers.
Another benefit is that it allows application developers to seamlessly leverage non-Sun ONE Application Framework infrastructure code that they might already have written to manage the document lifecycle.
This Model will limit its ambition to serving as a read-only Model. This means that the Model will support retrieval and display of XML document data, but it will not facilitate modification of document data. The implementation of full XML document update support is beyond the scope of this document. Furthermore, it is perfectly justifiable for a Model to limit its ambition to a well defined feature set, as long as the Model documentation makes it clear what is, and what is not supported. Application developers will then limit the use of the Model according to its documented usage.
Your XML Document Model component should support the following design-time functionality:
Your XML Document Model component should support the following run-time functionality:
To meet these requirements, you will design and implement the following classes:
Additionally, you will implement a custom Java template which the IDE toolset will use as the basis for application specific sub-types of our XMLDocumentModel.
Finally, you will edit the mycomponents complib.xml to add the new component to the Sun ONE Application Framework component library.
The Sun ONE Application Framework component model provides extensible Model component authors with the opportunity to specify an arbitrary implementation of the com.iplanet.jato.model.ModelFieldDescriptor interface. This is a very minimal interface. Each implementation of ModelFieldDescriptor must also be a JavaBean. Model component authors should design a ModelFieldDescriptor as a bean that can be configured by application developers to define a model field at design-time. Component authors, therefore have tremendous freedom to design model fields which can expose all the design-time configuration opportunity they want, as long as it can be expressed as a JavaBean.
In the example, your model field design-time configuration needs are trivial. The application developer needs to be able to configure each model field with an XPath expression.
1. In any Java editor, create the class mycomponents.XMLDocumentModelFieldDescriptor.
2. Implement the basic com.iplanet.jato.model.ModelFieldDescriptor interface.
3. Add a get and set method for the property XPath.
4. Add a get and set method for the property FieldClass.
This is an optional property. If populated, at run-time the Model will coerce the raw value retrieved with the XPath expression into the type specified by the FieldClass property.
After these steps, mycomponents/XMLDocumentModelFieldDescriptor.java should look as follows:
1. In any Java editor, create the class mycomponents.XMLDocumentModel.
2. Make XMLDocumentModel extend com.iplanet.jato.view.DatasetModelBase.
3. Make XMLDocumentModel implement com.iplanet.jato.view.MultiDatasetModel.
4. Implement the appropriate constructor for the component type.
All Model components must implement a no-arg constructor.
5. Add a get and set method for the property named "DocumentScope".
6. Add a get and set method for the property named "DocumentScopeAttributeName".
7. Add a get and set method for the property named "CurrentDatasetName".
This property will get a more user friendly display name "Base Dataset Path", but that work will be done in the XMLDocumentModelComponentInfo.
8. Implement the remaining methods that are required to fulfill your component specific requirements.
After these steps, mycomponents/XMLDocumentModel.java should look as follows:
Extensible components serve as base classes for application defined entities. Therefore, the Sun ONE Application Framework component model provides extensible component authors the opportunity to provide a custom Java template. The IDE toolset will, subsequently, use the component supplied template to create the application specific sub-type. Component authors can utilize the custom template to enhance the application developer's experience. Component authors may prepare the component specific Java template with a set of template tokens defined in com.iplanet.jato.component.ExtensibleComponentInfo. For token details see ExtensibleComponent API.
Component authors may also utilize any arbitrary Java constructs within the Java template (for example, import statements, methods, variables, interface declarations, and so on). Minimally, the custom template will ensure that the new Java class extends from the extensible component class. Component authors may also use the template as a means of communicating to the developer documentation inline in the source so as to provide "recommended steps" or conditions or boundaries to keep in mind while specializing.
In this example, the template will be kept minimal.
In any text editor create the template mycomponents.resources.XMLDocumentModel_java.template.
The template contents should look as follows:
import com.iplanet.jato.model.*; import com.iplanet.jato.util.*; |
The ComponentInfo class defines the design-time metadata that the IDE toolset requires to incorporate the component. In this example, you will extend an existing ComponentInfo and in true OO style, simply augment it. You could, of course, choose to implement the ComponentInfo interface from scratch, but that would be unproductive in this case.
In this example, you are going beyond the functionality revealed in the earlier component examples. Below, you are going to take advantage of a new metadata opportunity provided by the ExtensibleModelComponentInfo interface, the opportunity to describe an arbitrary Model Field type.
1. Create the class mycomponents.XMLDocumentModelComponentInfo.
2. Make XMLDocumentModelComponentInfo extend com.iplanet.jato.model.ExtensibleModelComponentInfo.
3. Implement the no-arg constructor.
4. Implement the getComponentDescriptor() method to provide the basic design-time description of the component.
5. Implement the getConfigPropertyDescriptors() method to identify which properties you want to expose in the IDE.
Note the use of default values within the ConfigPropertyDescriptor declarations.
6. Implement the getPrimaryTemplateAsStream() method to return a Java template file which you want the IDE toolset to use as the starting point for new classes derived from this extensible component.
7. Implement the getModelFieldGroupDescriptors() method to provide a design-time description of the model field type required by the Model.
Do not get confused by the extra level of indirectness suggested by ModelFieldGroupDescriptor on top of ModelFieldDescriptor. The ModelFieldDescriptor is the vital feature for you to focus on. The ModelFieldGroupDescriptor is an advanced optional feature. Suffice to say that most Sun ONE Application Framework Model components can simply make use of the standard com.iplanet.jato.model.ModelFieldGroup.
After these steps, mycomponents/XMLDocumentModelComponentInfo.java should look las follows:
Note - In this sample code, String values have been embedded directly for ease of demonstration. Utilize resource bundles if you anticipate the need to localize your display strings. |
The component manifest has already been created in the earlier example. Now you will add additional information.
Note that you will add additional types of information not seen in the prior example.
The Sun ONE Application Framework library manifest must be named complib.xml. Within the JAR file, the Sun ONE Application Framework library manifest must be placed in the /COMP-INF directory.
1. Create/Open the file COMP-INF/complib.xml.
2. Add an extensible component element to declare the XMLDocumentModel component.
After these steps, the COMP-INF/complib.xml file should look as follows:
Note - For clarity, only the significant delta to the prior version of this file shown earlier is shown here. |
Jar up the component classes as you did in the first example, so that they can be ready for distribution as a library.
1. The name of the JAR file is arbitrary.
In this case, name it "mycomponents.jar".
2. You can omit the Java source files from the JAR.
3. You should include in the JAR any necessary ancillary resources, like icon images, or resource bundles.
In this case, you are now including several new classes and a Java template file.
4. The mycomponents.jar internal structure should look as follows:
1. Deploy the new version of the library into your previously created test application.
Important Sun ONE Studio note: The Sun ONE Studio will not let you delete or copy over a JAR file that is currently mounted unless this is done via the IDE using ANT tasks which share the same VM as the IDE and share the file locks. You should shutting down the Sun ONE Studio whenever you need to replace one of the JAR files that is currently mounted. If you are trying to test the new version of component library in a project that is already opened inside the Sun ONE Studio, first shut down the Sun ONE Studio. Once the Sun ONE Studio has released its hold on the old copy of the library JAR file, you can copy the new version of the JAR file over the old version. After successfully deploying the new version of the library, you can re-open the application in Sun ONE Studio.
If you have not done this before, complete the Sun ONE Application Framework Tutorial.
The new Model wizard should now look as follows:
Note - Depending upon the version of Sun ONE Application Framework, you might not see all of the models that are shown below. The important point is that you see the entry for "XML Document Model". |
3. Select the "XML Document Model" from the component list and complete the wizard.
Take the default settings and let the wizard create "XMLDocumentModel1" for you.
After the wizard completes, you can see that the IDE toolset has created a new class based on the component supplied template.
4. To test your mode fully, create a second XML Document Model.
Your application should now contain two XML Document Models (XMLDocumentModel1 and XMLDocumentModel2).
Note the Base Dataset Name, Document Scope, and Document Scope Attribute Name properties.
Note above that the Document Scope property value is the raw integer 2. This is because XMLDocumentModelComponentInfo declared the DocumentScope property thus. The type is Integer.Type, and the default value is javax.servlet.jsp.PageContext.REQUEST_SCOPE. The net effect in the IDE will use the default Integer property editor which will express the raw integer value, in this case 2.
descriptor=new ConfigPropertyDescriptor( "documentScope",Integer.TYPE); descriptor.setDisplayName("Document Scope"); descriptor.setDefaultValue(new Integer( |
You would be correct in thinking that this is a poor user interface since most developers will not know that 2 corresponds to request scope. Therefore, as a follow up exercise, you will see later how to substitute a more user friendly property editor in place of the default Integer property editor.
To test your new Model component, you need a suitable XML document.
A test case will be contrived by placing an arbitrary XML file on disk, and at run time the test application will read the document from disk and place it into the request scope.
Your XML Document Model component does not care where the XML document comes from. In the real world, the XML document will probably be dynamically fetched by the application from the enterprise tier. That is of no concern to your XML Document Model.
a. In any text editor, copy the following XML into a file named "author.xml".
b. Place author.xml in the same application module directory as XMLDocumentModel1 and XMLDocumentModel2.
The code you will enter below will assume that it is in the same directory as your test Models. This is purely a convention of this exercise.
c. Review author.xml for a moment.
Notice that for a single author, there are many book entries. Now is the time to point out, that you will utilize the two models (XMLDocumentModel1 and XMLDocumentModel2) to access different parts of the same XML document. You will configure XMLDocumentModel1 to access the scalar author information, name, and details. You will configure XMLDocumentModel2 to access the non-scalar collection of books.
This approach was chosen when the XMLDocumentModel was designed because it simplifies both the implementation of the Model component, and simplifies the usage of the component within an application.
5. Configure XMLDocumentModel1 to access the scalar author information.
a. Select the XMLDocumentModel1 node.
b. Edit its Document Scope Attribute Name property.
Set the value to "authorDocument".
c. Leave the Document Scope and the Base Dataset Path properties unchanged.
d. Expand the XMLDocumentModel1 node so that you can see its Fields sub-node.
e. Select the Fields sub-node.
f. Right-click, and select the pop up menu's Add Field ... action.
This will automatically add a field with a default name.
In this case the default name will be "field1".
g. Repeat the previous step to create additional fields "field2", "field3", and "field4".
For the purposes of this exercise you will leave the names unchanged.
In a real application, the Model developer would probably change the field names to make them more descriptive of their role.
Select the Model Field Properties tab on its property sheet.
i. Edit field1's XPath property.
Set the value to the XPath expression "/author/name/@first".
j. Repeat the previous step, and adjust the XPath property for the remaining three fields as follows:
6. Configure XMLDocumentModel2 to access the "books" dataset.
a. Select the XMLDocumentModel2 node.
b. Edit its Document Scope Attribute Name property.
Set the value to "authorDocument".
c. Edit its Base Dataset Path property.
Set the value to the XPath expression "/author/works/book".
That is an XPath expression that will address the collection of book entries (for example, a Sun ONE Application Framework dataset).
d. Leave the Document Scope property unchanged.
e. Expand the XMLDocumentModel2 node so that you can see its Fields sub-node.
f. Select the Fields sub-node.
g. Right-click, and select the pop up menu's Add Field ... action to add "field1", "field2", and "field3".
h. Edit each field's XPath property to XPath expressions relative to the value of the Base Dataset Path property set above.
The models have now been configured. Now you need to create some Views to use the Models, and also provide some application logic to read the author.xml document from disk and store it in the request scope attribute "authorDocument".
Advisory: Read this next step fully before attempting, since if you follow the instructions correctly, you can save some time and effort by utilizing the full capability of the "New View" wizard. It is perfectly acceptable to create a ViewBean that will exercise the XMLDocumentModel1 without following the steps detailed below, and you can create the ViewBean according to your preferred style. But, for newcomers to the Sun ONE Application Framework, the following steps are, hopefully, the most concise.
a. Invoke the "New View" wizard.
b. Take the default values in the Associate JSP panel, and press Next.
c. In the Model Associations panel (below), expand the Current Application Components node until you find "XMLDocumentModel1".
That will cause the "XMLDocumentModel1' to appear in the Currently chosen models section of the panel.
d. In the Bind Display Fields panel (below), select all four of the Model fields that are available, and press the Add Fields button.
That will cause four entries to appear in the Bound Fields section of the panel.
After completing the wizard in the manner described above, you should find that the AuthorPage node looks like this.
The individual child display fields should be properly bound to the corresponding XMLDocumentModel1 fields.
8. Open AuthorPage.java, and add the following code to the constructor.
This code will read the "author.xml" document from disk and store it in the request scope attribute named "authorDocument", which is where the XMLDocumentModel1 expects to find it. The choice of placing this code here in the AuthorPage constructor is simply an arbitrary test stratagem. As stated before, the XMLDocumentModel does not care how or when the XML document is placed into the agreed upon attribute, as long as it is there when the Model is accessed. Note the extra import statements at the top. Also, note the getResourceAsStream method's parameter must take a parameter which reflects the name of your test application (for example, getResourceAsStream("/testmycomplib/main/author.xml").
9. Compile all the classes in the application and test run the AuthorPage.
Author should appear in the browser as follows:
Now you want to test XMLDocumentModel2 and its dataset capability.
For this you will need to create a TiledView. Essentially, duplicate the steps taken in creating AuthorPage, but select a "Basic TiledView" instead of a "Basic ViewBean" and associate it with XMLDocumentModel2 instead of XMLDocumentModel1.
a. Invoke the "New View" wizard.
b. In the Select View Type panel (below) select the "Basic Tiled View" component.
c. Explicitly set the Name to be "Books".
That will cause the "XMLDocumentModel2' to appear in the Currently chosen models section of the panel.
That will cause three entries to appear in the Bound Fields section of the panel.
11. The TiledView requires one additional configuration step that you have not seen before in this guide.
You need to configure the :Book TiledView's Primary Model Reference property to reference "XMLDocumentModel2". If you do not configure this property, the test run of this TiledView will show no data. That is a common Sun ONE Application Framework application developer error.
Edit the Primary Model Reference property (below), and from its drop down list select the "xmldocumentModel2" value.
12. Before you can test run the Books TiledView, you must add it to a ViewBean. To make this example more interesting, add the Books TiledView as a child of the AuthorPage. This is a good example of Sun ONE Application Framework's hierarchical view support.
Add an instance of Books TiledView to AuthorPage. Again, you can achieve this by selecting Books TiledView from either the Component Palette or the Component Browser, just as you did earlier with the various text fields and button components. Except this time, the component will be located in the Current Application Components section of either the Component Palette or Component Browser.
After adding Books as a child view, the AuthorPage node should look as follows:
13. You can now format the JSP associated with the AuthorPage to suit your taste.
By default when you add a container view child to a ViewBean, the IDE toolset will add the container view child and its children's tags to the ViewBean's JSP(s). The application developer may use the Synchronize to View action on the JSP node to batch remove tags for any child container view children. Take this opportunity to also add some basic formatting to the JSP so it renders more neatly.
a. Select and expand the AuthorPage's JSPs node.
b. Select the actual AuthorPage.jsp node.
c. Double-click the AuthorPage.jsp node to open the JSP file in the editor so you can edit it.
d. Add some basic formatting (for example, <p> and <br> ) to the AuthorPage.jsp so that you will get some separation between rows of Book data.
When done, the AuthorPage.jsp should look something like the following:
14. Test run AuthorPage again.
Make sure you select the ExecutePage (Redeploy) action, not the Execute Page action. Otherwise you will not see the effects of the recent changes.
The contents of AuthorPage.jsp should show up in the browser (because the user had accumulated the required tokens).
Not yet. Provide a custom editor for that "Document Scope" property.
Recall that the XMLDocumentModel's Document Scope property is currently vulnerable to user error, because it exposes a raw int value for direct editing. What you really need is a custom editor that presents the application developer with a fool-proof drop down list containing only valid choices. You would normally spend a little time and develop a custom property editor. The details of that are beyond the scope of this document, but can be found in any basic JavaBean reference.
Copyright © 2003, Sun Microsystems, Inc. All rights reserved.