This first article on future-proofing your Domino Applications will be to introduce the fairly well-known yet extremely
under-utilized - at least when it comes to IBM Lotus Notes/Domino - software design pattern known as Model-View-Controller
MVC is - simply put - separation of Applied Business Logics, Data Store, and Application User Interface.
So why is MVC so important?
Things change. Customers demand alternate client support for your applications. The business itself can change, directly requiring changes in what information is stored in and delivered by your applications. And at the end of the day, technology investments - and those who championed said investments - are put to the test: can the technology that you chose to implement several quarters ago deliver the usage experience and feature functionality required for today? How about tomorrow?
For the purposes of this article, I have create a simple demo of a Domino Web Application leveraging - I'll admit somewhat only in spirit - MVC. At the end of this article, you will hopefully have enough of an understanding of MVC and the specific techniques that I will use to deliver a more dynamic and more future-proof solution.
I was recently asked by a Lotus Notes Application Developer if there was a simple way to submit a given NotesDocument and create a pre-defined list of Response NotesDocuments. The application has pre-existing applied business logic that was written directly into the Lotus Notes Client - in the form of QueryOpen and QuerySave events, and dependant NotesItems that are dependant solely based on UI code.
The customer needs have evolved, and his users are now demanding duplicate functionality over a Web Browser Client.
The example solution that I will use to showcase several future-proofing design techniques will do the following:
1. Allow for the creation of a NotesDocument.
2. Allow for the applied business logic-based creation of a pre-defined collection of Reponse NotesDocuments of the given parent NotesDocument.
3. Allow for the deletion of a NotesDocument and all Response NotesDocuments based on the same applied business logic.
We will start off with the following Design Elements for our Example Build NotesDatabase - which I'll name docproc.nsf:
- Form Design Elements
- View Design Elements
- Page Design Elements
- Agent Design Elements
- Script Library Design Elements
Our first step will be to create our document
Form Design Element. document
will be our example of a Controller
- it's sole purpose is to consume our request/input into the system, where it will then pass it onto the Model
document is very simple, and it will handle both the Create and Update states of the Domino CRUD API. Remember that?!
It will contain 3 Fields:
Editable - Text: This field exists to show an ability to change NotesDocument NotesItem values via the Domino CRUD API.
Editable - Text: This field exists to mark the function performed by the Controller interacting with the Model. The idea is that a Published Data API for the docproc.nsf NotesDatabase would state th at this field can contain 3 values: Inactive, Active, and Purge.
Inactive really does nothing - and we'll define this as the default value in the View (as in MVC, and not View Design Element). A document submitted with an Active status will initiate the Model's Response NotesDocuments creation facility. Purge will - rather uncreatively - delete both the Response NotesDocuments Collection as well as the submitted NotesDocument.
Computed for Display - Text: This field - which is a special-named functional field, will relay the submission request from the View (again, MVC), to the Controller, and then to the Model. This field contains the following Formula:
"[http://" + @GetHTTPHeader("HOST") + "/" + @WebDbName + "/process?openagent&UNID=" + @Text(@DocumentUniqueID) + "]"
That's it for our document
Form Design Element. Yep - no WebQuerySave events or conditional fields or any other overhead. The only reason that you would need to add more fields to this Form Design Element is to name-match additional information you want to capture as part of the Domino CRUD API. Since we're only worried about title
and (more importantly) status
... we're done here.
Now, for those of you who follow my posts, you know I'm no fan of View Design Elements. They add bloat to the NotesDatabase and are often misused resulting in slow render and response times for NotesDatabase-based solutions.
I'm being purposefully simplistic this evening - I don't want to confuse potentially-new concepts - and using the markup View Design Element to house our document and response NotesDocuments. All this does is show documents and responses in hierarchy via XHTML Table TBODY Element rows classed to their specific type (document vs. response). Set the View Design Element to Treat Contents as HTML and you're done.
You can check out the example download of the build for any more details if you need them.
Now, let's create our View/Controller hybrid Page Design Element: index.html. Not only will we set this as the Default Launch Object for our NotesDatabase when opened via a Web Browser Client, but index.html will contain our document NotesDocument Create and Update HTML Form Element.
Pretty standard XHTML markup here. Only thing Domino-specific
are the Computed Text Elements and the Embedded View - our markup
View Design Element - (which I've previously mentioned will simply render the submitted document
NotesDocumentCollections as XHTML Table TBODY Element rows).
The Computed Text Elements are a little more complicated.
To explain what I'm doing with these Computed Text Elements, I'll first explain the would-be Data API logic I'm using here to either Create, Read, and Update a given document NotesDocument.
The index.html Page Design Element relies on a QueryString Parameter named UNID:
Each Computed Text Element checks for this QueryString Parameter, and if populated either loads information from the NotesDocument into the XHTML Form Element Input and Select Elements, changes said XHTML Form Element's processing agent to Update instead of Create, or verifies that there are no issues retrieving the NotesDocument via the designated UNID Parameter value. Where an error/issue is found, a META REFRESH is written to the XHTML He ad resulting in a 0-second redirect to index.html.
At this point, while we're using some pretty unconventional methods to facilitate Domino CRUD, we're not really extending the feature functionality. This is where our $$Return comes into play.
The session redirection post successful submission of the document NotesDocument to the process Agent Design Element allows us complete control over not only what is being added to the referenced document, but it gives us literally unlimited possibilities.
For the purposes of this example however, I kept things simple enough:
set doc = processdocument(s.CurrentDatabase.GetDocumentByUNID(UNID), s)
Print |[| + Join(s.DocumentContext.GetItemValue("HTTP_Referer"), "") + |]|
Leaving the details of the Subroutines and Functions used to harness the passed-thru UNID QueryString Parameter from the $$Return-spawned URL call to the process Agent Design Element, I'm simply using that UNID value to get a handle on the recently submitted document NotesDocument and submitting that to my processdocument Function (which, of course, resides in the processingengine Script Library Element).
Care to see this in action? Check out the Advanced NotesDocument Processing Online Demo. From there, you will be able to Create, Read, Update, and Delete document NotesDocuments, and use the status values to either create 3 response NotesDocuments or purge both the document and any response.
Consider this? I can place my entire business logic into the processengine Script Library Element. I can submit a single or a loop-through NotesDocumentCollection for processing. And since it's a Script Library Element and not part of the Agent Design Element or - even worse - the Form Design Element, I can make the same exact calls that I'm using in the Domino-generated Web Browser Client and change the User Interface to a Mobile Browser Client or even submit the uidoc.Document on the PostSave event from a Lotus Notes Client.
Still in the mood to consider things? Imagine fully utilizing the Domino CRUD API and moving away from a Domino-rendered index.html Page Design Element and onto Domino Web Services to facilitate Blackberry Rapid Application Development or porting a UI onto Adobe Flash or Air, writing your front-ends in Dreamweaver or creating an iWidget for Websphere?
By establishing a simple Data API (via the Domino CRUD API), moving any applied business logic out of the specific UI Design Elements, and employing MVC-style design techniques in our Domino Application Development efforts, we've created a system where we are not limited by the preconceived limitations of the given technology platform.
Advanced NotesDocument Processing - Example Download
... so when's the last time you said "Notes really can't do that..."?
(Author's Note: Article originally posted on http://www.dominoguru.com/pages/mvc_dominoappdev.html.)