Jo Grant and Craig Wolpert are members of the IBM Workplace and Lotus Software ISV Technical Enablement team. This article is the result of information gathered while developing a Composite Application sample for Notes 8. It is one is a series on developing composite application. We will post more articles to this forum as they are completed. Please provide feedback on the content and how it is presented by Monday (2 April 2007).
Developing Composite Applications: Notes Components
Jo Grant, Dan Kehn, Craig Wolpert
This article mentions a sample which is currently under development.
This article mentions screenshots and a sample currently under development. This document will be updated with screenshots at a later time.
Review Composite Applications information distributed with Domino Designer 8 Help
Review the Composite Applications Tutorial and Documentation - "Building Composite Applications for IBM Notes 8"
Read the article "Designing Composite Applications: Component Design" (suggested)
Composite applications are a key element in a service-oriented architecture (SOA) and contextual collaboration strategy. They support business flexibility for companies and organizations who wish to rapidly respond to changing demands in today's competitive markets. Composite applications are aggregations of multiple components that are loosely coupled to support component resuse. Changes in data values in one component can be broadcast through properties. These are then wired to actions in other components to receive the change notification and react to it. Components can be reused in multiple composite applications. The ability to combine multiple technologies into a single application provides significant business value. It enables companies to protect and extend their existing assets with increasing degrees of flexibility, and to respond quickly and cost effectively to their emerging business requirements, with applications that are significantly easier to create than multiple application development environments.
The IBM(R) WebSphere(R) Portal composition application model is provided in a Notes-style approach. IBM(R) Lotus(R) Domino Designer(R) has been extended to leverage the property broker, as well as to provide a more intuitive user environment. Notes applications can be surfaced as one or more Notes components in a composite application. Notes 8 also supports the inclusion of Eclipse components and a composite application may have any combination of Notes components and Eclipse components. These may be just be presented together in the same UI for on the glass integration or if extended to use the Property Broker will fully be able to interoperate with each other. You can define composite applications using the Composite Application Editor or the WebSphere Portal Application Template Editor.
Chapter five of the Composite Application Toolkit User's Guide discusses how to build Notes components. It gives a reference to the APIs used and several examples. There is also a tutorial that walks you through the creation of a simple Composite Application based on Notes components. These give you the basic understanding necessary to create basic components from scratch. This article builds on that information and gives you some tips and techniques for transitioning your existing Notes applications to Composite Applications. This does not present an exhaustive list of everything possible with the features given. During the course of this article we will look at the Discussion Database template as our example of an existing Notes application.
When you approach Notes Application development you normally think in terms of What Forms will I build? How will I list them in Views? How will I put all of these together into framesets? And so forth. It is very tempting when reconsidering your Notes Application as a Composite Application to just take these building blocks you already have and build components for each one of them.
When you look at low-level design constructs, such as Forms and Views, you might often use one, or a number of these, to represent a single logical unit. For example you might have several views that show a selection of data in different ways. Or a number of forms might view an abstract data type depending on the state of it in a workflow. Components for a Composite Application are best designed around the logical units that form an application and not the Notes design constructs that happen to be used to articulate them. (Obviously you want to be able to useas many of the existing design constructs as possible! But we are talking at the design level at this point. We'll come back to that when we talk about implementation.)
When you look at the higher level aggregating constructs, such as framesets, pages or outlines, they are mainly used for building up a specific user interface. These are often designed for expressing the application in the best way as complete Notes application in and of itself. The goal of good component design is to design UI elements that can be used in a variety of ways both in applications whose focus is on the information represented and also in other applications as bridges to relate other focus data to the data they represent. Although these two goals are not opposites, they are seldom in convergence.
So if you do not base the approach of componentizing your Notes application based on the design constructs present there, where do you start? The answer is, quite simply, to go beyond the design constructs that your application has been articulated with and go back to the original abstract design that those constructs were based on. Almost every Notes application is based on one or more data element types. This is a unit of information, represented in a Notes Document with a collection of values. The business logic of the application defines the lifecycle of these documents, how the values in them are constructed, and how the documents relate to other documents. We then have Forms that provide a window into these data elements and present them to the user in specific ways. We also have Views that show collections of documents and show some of their relationships.
For example, in the Discussion Database the basic data element is an individual's contribution. At a basic document level this has a value that is the subject, another value that is the body of the content, and a number of others such as the author, the date composed, etc. The business logic of the database arranges these documents into discussion threads, with a child-parent hierarchal structure. We have Forms that show these based on three basic types of relationships defined by the business logic: Main Topic, Response and Response to Response. And there are a number of views that show these documents based on this hierarchal structure, sorted into categories, indexed by author, by date, etc.
When we look at it in this manner, there are a number of abstract ways we can look at these elements as components:
Detailed Information - this is a component that displays most of the information of a single data element with verbosity appropriate for when it is the center of attention
Summary Information - this is a component that displays some of the information of a single data element with verbosity appropriate for when it is in the periphery of attention
Edit Mode - this component provides a user interface for altering the content of the information of a single data element
List - this is a component that displays a collection of data elements
Constrained List - this is a component that displays a subset of data elements constrained by some factor
Needless to say, this list is not exhaustive. Depending on the complexity of your application there may be other abstract types that arise. Similarly some of these types lend themselves to several different implementations. If your Notes application has several data elements you may have one or more of these abstract types of components for each of the data elements.
This list is presented here as a starting point for thinking about how you might project your Notes application as a collection of components. We now look at each of these component types in detail, and discuss methods of implementation.
General Component Patterns
One of the challenges of creating components is that you are designing against unplanned situations. The best components will be those that are usable in the widest variety of areas. However, it is hard to be all things for all people. At the highest, most general, level we can look at how collections of components are deployed to get some guidance for our design. Two patterns, in particular, seem to occur more frequently than others:
<screenshot> Narrow and Wide Columns. Many page layout environments let you choose amongst several styles. These often come down to adding a fixed number of "narrow" columns or "wide" columns. Since this metaphor is fairly common, it makes sense to target components for use in a "narrow" or "wide" columns. This allows you to better gauge the UI for its target environment. For example if the target environment was a wide column you might use field labels to prefix fields in the same row. Where if you to be targeting a narrow column you might adjust it so that the prefix labels were vertically above the target fields. In our Discussion Database example here we will produce a Detailed Information component that contains all of the information about an entry in a discussion thread. Because of the real estate required this would be suitable as a wide column component. We will also produce a Summary Information component. This contains less information and will be displayed in a compact form suitable for display in a narrow column.
Similarly if you were going to display a view in a narrow column you might just choose a small number of pertinent columns of information to display. Whereas if it was for a wide column you might expose more columns. In our Discussion Database example we will produce a general List component, which shows hierarchal details of discussion threads. This is suitable for display in a wide column. We will also produce a Constrained List component which displays documents in a single category or by a single author. This would be suitable for display in a narrow column.
<screenshot> Focus and Periphery. This layout technique uses a dashboard metaphor. There is one central component which is the focus of attention. Then arranged in the peripheral vision are other components which give additional information related to the context established by the focus component. For component design, this arrangement gives you the guidelines for designing for if your component is to be the center of attention or of it is to add supplementary information to some other central component.
In our discussion database example some of the large screen real estate components like Detailed Information or Edit Mode components are good candidates for being designed for being the center of attention. Others, like Summary Information or Constrained List are best suited for ancillary placement since they depend on other context setting values for their display.
Choosing Component Properties
Since each of the component types we are discussing is in relation to a data element type, they are going to tend to share a common set of properties that they expose. Typical properties exposed are most of the fields in the data element. Although these fields are not defined by the entries in the forms or the columns in the views of the application, this is a handy place to look to work out which are the more important ones. You should strike a balance between exposing every possible field (computed or otherwise) and only the minimum needed. Identify the properties that other components might be interested in. But err on the side of too many rather than too few for this criteria.The best components are reusable in areas beyond their original conception. So the more properties you expose the greater the chance for reuse and the less changes you will have to make down the line. But too many properties can clutter the wiring UI making it difficult for the assembler. As a minimum you should start with the properties necessary to complete the immediate task you need to accomplish. Then you should add in all the one that you can think of a possible use case for. Lastly you should document the rest in your development notes as possible future ones to expose. For the purpose of reference lets call these our Data Model Properties.
In the discussion database we select the From, Subject, and Categories fieldsas our Data Model Properties.
Choosing Component Actions
With the exception of the Edit Mode Component, actions are typically used to search and select a data element type. This is common to many of the components discussed. So it makes sense that these will mostly likely be the same across sets of components. On the simplest level candidate actions are the Notes definitions that can uniquely specify a document: UNID's and Notes URLs. The next level up then are identifiers that an application defines that can also be used to identify a document. These are usually fields like the name or account ID. For speed of access these are typically related to indexes on views. They should not, in general, be values that may return multiple documents.
If you are implementing searches that are nontrivial it is good practice to promote the code for doing this into a shared libraryor to use shared actions. That way the actions in your Detailed Information Component and all of your Summary Information Components can use the same code. There is less scope for typing errors and you have a single point to update for changes and bug fixes.
Choosing Data Types
Each property or action exposed must have a data type associated with it. In order for two components to communicate with each other the two wired elements need to be of the same data type. A company is strongly advised to identify a process whereby consistency in declared data types is maintained across all units building composite applications.
For each element in our Data Model Properties you need to assign a data type. You can first check the data types defined by Notes. If the type of your field in your form directly corresponds to one listed there, you should use it. Second you should check in your own company's registry. The more common data types defined across the company the better components will interoperate. If you do not find an appropriate data type in either place, then you should consider defining a data type to reflect its value. If you do so, you should communicate this with whoever maintains your company list. That way if someone else later wants to write a component that communicates with yours, they will know what type to use.
Alternatively if you have a field that is truly notational only, you might consider assigning it a generic "xsd:string". In such cases you might also consider that if such a field is so generally defined, then maybe you don't need to publish or consume it. For example, a category is a common property which might be published by many components. Defining a Category Data Type would be a good convention for all components using a category.
Detailed Information Component
This component style gives full details on the referred data element. It's suitable for display in a wide column or in the center-of-attention position. It is, typically, the document rendered in the form it is currently set to. Properties. The is the typical case for component properties and those in the Data Model Properties should be used. Actions. As with properties, this it the typical case and the actions in the Data Model Properties should be used. Implementation. Although you can create a notes URL that points directly to a form (e.g. notes://server/db.nsf/MainTopic?OpenForm) and can use that to create a component, that will bring up an empty form on top of a new document. We want to be able to bring up a specific document with that form. So we need a different approach.
The solution is to create a frameset that has an almost invisible left hand frame and a placeholder right hand frame. In the left frame we load a document we create just to house our recipient actions. These accept their values, do the lookup, and if a document is found, use a combination of SetTargetFrame and EditDocument on a NotesUIWorkspace object to bring up the document in the adjacent panel.
Note: after we load up and display the discovered document, we should also publish all the values of it to the properties we have defined. This will trigger further actions in any wires that have been connected to it.
In the sample examine the frameset called DiscussionDetail for how the frameset was put together. And examine the form called DiscussionDetailActionPanel to see how the form to do the lookup and switch was done.
Edit Mode Component
This component lets you edit a document. In a typical Notes application when you wish to edit a document you get the form for the document in edit mode displayed in full screen. In a composite application we can improve on this by bringing up an Edit Mode Component for the data element in a Focus and Periphery style page. Instead of the normal method where a user might switch tabs or applications to cut and paste data into the document they are composing, we can arrange components in the periphery of the page that have data that can be added and transmitted through wires.
It is possible that in some implementations that your Edit Mode Component is just a variant of your Detailed Information Component. This can be advantageous as you have less components to manage. But it can also make the individual component itself more complex for creation, maintenance and use. Consider the option and decide what constraints are important for your application. Properties. Again, best selection of properties to expose are those identified in your analysis. Unlike either the Detailed Information Component or the Summary Information Component we don't want to just broadcast their values when we load it up, but we want to broadcast it as they change. This is so connected components can update based on values that you are composing. Actions. Again, best selection of actions to expose are those identified in your analysis. Additionally there should be actions corresponding to most edit fields in the form. When these actions are triggered they update the form's value with the incoming value. For example, say you had a purchase order form with a cost center field. One of your periphery components might be something that let you browser your company's cost centers and select one. When selected you would then want it to go and update the cost center field in your purchase order. Exposing these fields as actions let you implement this scenario. This pattern of components is discussed in more detail in the article titled "Designing Composite Applications: Composite Application Design Patterns". Implementation. The implementation of this is very similar to that used for the Detailed Information Component. Since we need to load a specific document, we use a frame set and action panel to receive the search actions, find the document, and load it into the display frame. That much gets basic display working.
Next you have to implement the field exchange. On each edit field you can hook the Exiting LotusScript event. Add code there to get the new value of that field and publish it to the property broker. For the actions, add an action for each incoming field. Get its value and set it into the field in the form.
Note: where you might have several edit forms, as in the discussion database, you will need to do this in each form. Common code is best stored in libraries to make things easier.
In the sample examine the frameset called DiscussionEdit to see the frameset that houses this. There is a form called DiscussionEditActionPanel that has the basic search and display actions in it. Then you can look at the Main Topic, Response and Response to Response forms to see how the field exchange is implemented.
Summary Information Component
This component gives a selection of details on the referred data element. It's suitable for display in a narrow column or as a peripheral component. There may be several different Summary components, each one giving a subset of information relevant to a particular information domain. Properties. Even though only a subset of the data element's properties are displayed, there may be good reasons that other components might want programmatic access to the other values. Since property publication is done at a code level, the fields are accessible even though there is no display for them. The best strategy is to just publish all of the Data Model Properties. Otherwise an application assembler down the line might choose to use a Detailed component when a Summary one was more appropriate just to get at the extra information exposed. Actions. In general it is a good idea to expose all the actions in the Data Model Properties. However it may not be necessary to implement actions relating to keys that are not displayed. Implementation. The form used to display a Notes document is stored in the "form" field in the document. In this case we want to display the document in a different way than the form it is encoded to use. So we cannot use the technique we used for Detailed Information Component.
Instead we create a specialized form that displays the subset of information we want. We call this a "facade form". At no point are we actually going to store a document created with this form into our database. We are only going to use it to display values from another document. A very simple way to do this is to create a copy of the original form, and then delete all of the fields we are not interested in. This preserves as much of the UI look and feel as possible. Reuse may be possible through the use of subforms if the data layout is amenable to it.
We add appropriate recipient actions to this form to accept the search values to find the appropriate document. Once we have a target document we can read the values we want to display from it. Unfortunately we cannot write the values directly into the fields. We can only write values into fields in edit mode, and we do not want to display this. That would give the impression to the user that they are allowed to change them. That is not the role of this component. So, to get around this, we need to duplicate each field we wish to display. We make these fields computed, and link their value to the original corresponding fields. We then mark all of the original fields as hidden.
A simple way to do this is to cut and paste all of the fields in the form. When they are pasted back in Notes automatically suffixes them with "_1". Go to each of these and make the adjustments as above. In our action code we update all of the original fields, and direct the NotesUIDocument to refresh to do the update.
In the sample examine the form called DiscussionSummary to see how we did this for the discussion database. The Action Property setDiscussionSummaryDiscussionID performs this work.
This component is for listing a type of data element in a variety of ways. It is suitable for wide column use or as a center-of-attention component. Most simply it corresponds to a Notes view. However in many circumstances there are, in fact, a number of views that might relate to the viewing of a single data type. But also Notes applications frequently include navigators that list views of multiple data element types broken out into major sections. Usually when designing components the most flexible strategy is to create components that relate to a single data element type. That way if the application assembler is only interested in one data element type, they can restrict the list to that type. If they are interested in more, than can always add both in a tabbed view. Properties. The primary property that you want to expose from this component is the currently selected document. This can be done by broadcasting all of the properties identified in your analysis. Alternatively you may limit it to the fields corresponding to the input search keys defined in your analysis of appropriate general actions. Actions. Analogously this component should consume all of the general actions. If a successful match occurs, the selection state is changed to reflect the new document. Additionally when the new selection is made, the properties should be broadcast reflecting the new data. Implementation. Each view that is going to participate in the component needs to be enhanced. The onSelect LotusScript event is a good place to promote the current selection from. When invoked, the current selection can be derived, the document retrieved, and the properties published. Note that since views can contain hierarchal construction elements such as twisties that refer to a category and not an actual document, you should always check to make sure that the current selection is an actual document.
If your design calls for only exposing the current selection or a subset of fields that also happen to be view columns, an easy way to accomplish this is by setting a property in the column's infobox to automatically publish the value to the property broker.
Similar to other components actions can be created on the view to consume the defined actions and change the selection appropriately.
In the simple case where you have just one view for the component, you can just document the URL for that view and use that in adding the component to the palette in the Composite Application Editor. Where you have multiple views you need to construct a frameset. In one frame you can place some sort of selection mechanism. This can be an outline or a special form with buttons that replace the other frame with the appropriate view. The URL to document then is the URL for the frameset.
In the sample examine the frameset called DiscussionList. This then refers to the DiscussionListButtonPanel form which has buttons that load the individual views. Debugging Tip . An onSelect is triggered for every focus change. If you try to use the interactive LotusScript debugger you will get successive firing of this event for each line of code stepped through! For debugging you might consider creating a manually triggered action that invokes your code for broadcasting a selection change. Once it is working to your satisfaction you can copy the code into the onSelect method for final testing and production release. Additional testing and debugging tips are covered in the article titled "Developing Composite Applications: Debugging".
Constrained List Component
This component is similar to the List Component, but what is listed is constrained to a specific domain. For example you might only display data elements belonging to a certain category, revenue range, or author. It could be designed for either wide or narrow column use. Like the Summary Information Component you might have several of this type constrained to different information domains. Constraints can be simple single values, or they may be a compound value, or multiple types. An example of multiple types is when you want to constrain a view by category and sub category.
An alternative method would be to have fixed constraints. You may wish to have a display that only ever displays documents in a certain state. For example purchase orders that have been closed.
You can even mix and match types. For example a Constrained List Component that lists sales leads by status and owner, where the state is fixed to closed, but the author is open to being wired. Properties This exposes all of the same properties as the List Component. Note that you should also have a well defined value for what you are using to nominate the currently selected record for the case in which no record is selected. If constraints are imposed that result in no matches you need to be able to broadcast the fact that nothing is selected. Actions. This exposes all of the same actions as the List Component. Additionally you need to expose actions to consume the different constraints. Implementation. Unlike the general List Component in this case we are only ever dealing with a single view. But since we are constraining its selection we cannot promote the view as it stands in the database. Instead we create a special form and add the underlying view as an embedded view. We then add a field to the form and indicate the embedded view is constrained by that field. We also add actions to the form to react to property broker actions, read the values, and set the constraints into the field. An additional advantage is that there are a number of properties you can set on the embedded view that give you a greater control over the view's display.
This scenario is demonstrated step by step in the Composite Applications Tutorial.
In the included sample examine the Form called DiscussionListByCategory.
Putting Everything Together
Now that we've defined a bunch of components what do we do with them? Well, the simplest thing is to re-assemble them in a way that gives the same functionality as the original discussion database. Overview Page. The opening page of our composite application should give an overview of the database. We might have a wide column in which we place a List Component, and a narrow column in which we place a Summary Information Component. We then wire the current selection of the List Component to the Summary Information Component. This way as documents are selected they get highlighted like a controlled preview pane. Detail Page. This page would have a Detailed Information Component in the center-of-attention place. This would give all of the primary information for a specific discussion item. We might then put in the periphery a Constrained List Component to display other items from the same thread and/or the same author and/or category. Edit Page. This would be similar to the Detail Page, but we would have in the center-of-attention the Edit Mode Component.
What Have We Achieved?
On the surface it appears as if we have taken a discussion database, broken it down into components, and then reassembled it back again from components. If the resulting functionality is the same as what we started with, what have we achieved?
In terms of raw functionality of a discussion forum, we have made no steps forward However just by doing so we have already gained the ability to arrange components to provide a context and have different components be the center of attention. As described above, the Overview, Detail, and Edit pages each have a different center of attention. A key advantage to a Composite Application architecture is integration with other applications; both Notes applications and other applications. For simplicity we've just been discussion one application: a discussion database. In the real world, there would be several other applications that we can now leverage in our discussion database and that can leverage the discussion database in them. Consider the following scenarios.
Scenario 1: Say that we have several discussion databases. One discusses features for a product, another discusses the release schedule, and a third discusses customer reports. If all three used the same terms for categorization, it would be possible to add Constrained List Components to each of the database's Overview pages that listed topics in the same category in the other database. For example if you were in the Product Features database on the Overview Page looking at the "Return on Investment" category, In the periphery would be displayed the release schedule line items and customer reports that have to do with "Return on Investment". Similarly we might be on the Detail page looking a specific record, you might have a peripheral view of articles in the other databases by the same author.
Scenario 2: Say that we have a Sales Lead application for tracking customers and leads for those customers. We also have a discussion database for discussing those customers and leads. If both were composite applications we would be able to easily add components so that while examining leads for a particular customer we would also get a snapshot view of what discussion are taking place about it. It would also give us a quick launching platform to participate in a discussion or start one related to the context we are viewing.
Scenario 3: Say that we have a back end system for tracking customer calls. It manages the basic workflow, but was not built to track the interactive discussion that takes place to resolve incidents. If that was projected as a series of Eclipse components, they could be surfaced in a Composite Application integrated with components from a Discussion database to add that interactive discussion capability.
This article has charted the simple steps for extending an existing Notes application into components suitable for use in constructing a Composite Application. It has also outlined some ways these components might be used. As an example we used the Discussion Database that ships with Notes. The included code can be used off the shelf for that application and can serve as the basis for your own efforts on your own applications.
After you understand how to extend a Notes application to include components. The next step would be to use this process on an application which includes multiple Notes databases. The power of composite applications is the ability to provide a context which combines information from multiple components and leverages that context when performing tasks. The scenarios above provide some examples of composite applications integrating multiple components from multiple Notes databases and external applications.
Feedback response number CWOT6ZFLD4 created by Craig Wolpert on 03/19/2007