XPages MVC: Experiment II, Part 1
Wed May 23 15:38:00 EDT 2012
- XPages MVC: Experiment I
- XPages MVC: Experiment II, Part 1
- XPages MVC: Experiment II, Part 2
- XPages MVC: Experiment II, Part 3
- XPages MVC: Experiment II, Part 4
As I've mentioned a couple times, my largest XPages app to date is the site I did for my guild's forums. The forum part itself isn't particularly amazing, considering it's almost harder to NOT write a forum in Domino than it is to write one, but it gave me a chance to try my hand at abstracting data access away from the XPage.
I put "Part 1" in the title because I figure it will be best to break the topic up into at least three parts: the overall idea and the result, the structure of the model and collection classes, and some nitty-gritty bits about how I get the data out of the back-end classes.
My first draft of this site was straightforward, from an XPages perspective: I mapped XPages to the corresponding Forms and used a bit of Server JavaScript here and there to pull in bits of support information. This worked pretty well at first, but quickly ran into code and speed scalability issues. Just looking at a "Topic" page, the following data needs to be looked up from outside the Topic document itself:
- The name and ID of the parent Forum document
- The name and ID of the parent Forum's parent Category document
- Whether or not the topic is marked as a "favorite" for the current user, which is stored in a prefs doc for the user
- The collection of Post documents for the Topic
- For each Post document:
- Summary and rich text data from the document
- The display name, title, and signature of the posting user, which are stored in their Person document
- The number of posts from the posting user that are visible to the current user, updated live (heh)
- Whether or not the current user has rights to edit the Post document
- Any surrounding page elements, such as the count of unread topics from the front page, the "who's online" list, etc.
As you can imagine, writing each one of those as inline SSJS turned into a hairy, slow mess. And that's just for the Topic page! That's leaving out the other pages, such as the forum index, which has to show a tree hierarchy of Categories and Forums with up-to-date Topic and Post counts.
I tried wrapping these things up into SSJS functions in a script library, which helped a LITTLE, but it still sucked. The clear solution was to wrap these all in proper model objects and, after a number of revisions, I came up with a pretty good solution.
Conceptually, the back-end structure consists of:
- Collection Managers. These are analogous to Views, in that there's one per document type and they communicate with a similarly-named uncategorized View with many sortable columns. I write methods in these managers to allow for returning an appropriate collection for the circumstance (e.g.
getPostsForForumId(...)
andgetPostsForTag(...)
), as well as generic methods for getting arbitrary collections for a given key, sort column, and FT search query. - Collections. These are analogous (and often wrap)
ViewEntryCollection
s. They implement theList
interface to allow for use inxp:repeat
s and handle efficiently getting the needed model objects and re-fetching the View and Collection if they're recycled away. - Model Objects. These are what you'd think:
Post
,Topic
, etc.. These provide getters/setters for the fields of the document, getters for associated collections (e.g.topic.getPosts()
), and handle saving the document back to the DB.
The net result is that pages went from having giant blocks of lookup code (or SSJS function calls that pointed to giant block functions) to nice little EL expressions like #{category.forums}
and #{forum.latestPost.createdBy}
. As importantly, this allowed for a lot of caching to make these relational operations speedy when dealing with live data in a Domino DB.
Next time, I'll go into some specifics about how I structured the collection and model classes.
Patricio M. Ros - Wed May 23 16:33:41 EDT 2012
Thank you for looking for a better XPage development experience (and share it). Thank you for XPages Ruby too. Go on!