dominoGuru.com
Your Development & Design Resource
Leveraging MVC-style design techniques in Domino Application Development
07/31/2009 12:46 AM by Chris Toohey
(Note: Cross-published to the IBM Domino Designer Wiki)
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.
Build Synopsis
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:
- Allow for the creation of a NotesDocument.
- Allow for the applied business logic-based creation of a pre-defined collection of Reponse NotesDocuments of the given parent NotesDocument.
- Allow for the deletion of a NotesDocument and all Response NotesDocuments based on the same applied business logic.
Example Build
We will start off with the following Design Elements for our Example Build NotesDatabase - which I'll name docproc.nsf:
Form Design Elements
document
View Design Elements
markup
Page Design Elements
index.html
Agent Design Elements
process
Script Library Design Elements
processingengine
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:
title
Editable - Text: This field exists to show an ability to change NotesDocument NotesItem values via the Domino CRUD API.
status
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 that 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.
$$Return
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 and response 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
:
http://server/database/index.html?open&UNID=<N
otesDocument Unique ID>
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 Head 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"), "") + |]|
End
Sub
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.
Conclusion
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..."?