posted Nov 15, 2011, 1:30 PM by Eric Patrick   [ updated Nov 20, 2012, 6:33 AM ]
Standard QBO interfaces have been rewritten for QBO3 to support additional use cases. This post is a working document on the requirements for several of these interface.

Archictecture Question

Take three uses:
  • ISmartWorklist: support membership in a smart worklist
  • IBillable: support automated creation of ledger items
  • IDecisionStep: support membership in a workflow
What is the best way to handle calling the code for each of these interfaces?  Options include:
  • Use a database trigger to populate some queue (e.g. QBO 2 Events)
    • pros: any method changing the table will result in an item in a queue
    • cons: a lot of items in the queue, triggers slow bulk operations down
  • Use C# event infrastructure to raise appropriate events when a class is being inserted or updated
    • pros: does not impact database performance, can filter items in the application tier
    • cons: extra overhead on every insert/update, does not trap for updates made outside the application tier
  • Poll the database for possible changes
    • pros: any method changing the table will result in an item in a queue, no trigger contention
    • cons: need an UpdateDate index for every table being polled to prevent constant table scans
ISmartWorklist use case

Most smart worklists are basically defined by something like 'all Valuations with a Status of X'. Assume we have:
  • Worklist A: all Valuations in a Status of QC Review
    • filter : Status IN ('QC Review')
  • Worklist B: all Valuations in a Status of Awaiting Assignment
    • filter : Status IN ('Awaiting Assignment')
  • Worklist C: all Valuations of type Appraisal not in a completed Status
    • filter: ValuationType = 'Appraisal' AND Status NOT IN (Final Status List)
Abstractly, we have two things to consider for each smart worklist:
  • Add stuff that's not there but should be, and
  • Remove stuff that's there but should no longer be
Add stuff:

INSERT ... FROM Valuation WHERE {Filter.RecentlyUpdated} AND {Filter.SmartWorklistFilter}

Remove stuff:

UPDATE ... FROM Valuation WHERE {Filter.InSmartWorklist} AND NOT ({Filter.SmartWorklistFilter})

The {Filter.SmartWorklistFilter} is business-driven, and not really subject to this architectural decision.

The {Filter.RecentlyUpdated} and {Filter.InSmartWorklist} as very much the subject of this architectural decision.

Revising our options for implement ISmartWorklistMember, the trade offs are:
  • Database trigger: 
    • pros: {Filter.RecentlyUpdate/InSmartWorklist} narrow to a primary key
    • cons: every update puts an items in a queue, with db trigger overhead; many of these queued items won't impact the worklists at all
  • C# events: 
    • pros: {Filter.RecentlyUpdate/InSmartWorklist} narrow to a primary key
    • cons:  every update puts an items in a queue, with C# event overhead added
  • Polling:
    • pros: SQL will efficiently process the {Filter.SmartWorklistFilter} clause against multiple rows (e.g. all recently changed Valuations)
    • cons: {Filter.RecentlyUpdated/InSmartWorklist} are more expensive than a primary key check
IDecisionStep use case:

For workflows, one know whether an object is part of a workflow from the moment it is created. Decisions must be made aware when an object is:
  • Completed,
  • Cancelled, or
  • has an error condition

File Streaming (IFileObject)

Use cases include:
  • Compression
  • Encryption
  • File Watcher
  • List
  • Version control
  • Returning FileInfo (e.g. size on disk, etc.)

Document Generation (IAttachmentTemplate)

Use cases include:
  • Passing data via IDataReader, XmlReader 
  • Complete control over file naming
  • Saving to multiple file locations (e.g. local and client's FTP site)
  • Producing a Zip file of 10,000 BPOs
  • Open XML SDK integration
  • Bulk generation (e.g. generate a contract for 10K brokers)

Queuing (IQueue, replacing IEventQueue)

Use cases include:
  • Replacing existing EventQueue calls
  • Generating 10,000 documents
  • QDS integration
  • Supporting callbacks (QDS posting data back)
  • Geo-coding 10,000 Contacts against Google or Bing

Workflow (IDecisionStep)

Use cases include:
  • No need for Events to run workflow
  • Windows Workflow Foundation integration
  • Synchronous or asynchronous processing
  • Strong error trapping
  • Strong logging
  • Setting parent status on start or completion

Templates (ITemplate)

The ITemplate interface provides functionality for templated classes, such as ProcessTemplate, ImportFormTemplate, AttachmentTemplate, and DecisionTemplate. Each of these classes determines the behavior of an instance class (Process, ImportForm, Attachment, Decision, etc.).  ITemplate defines the properties all templated classes share, including
  • AppliesTo (string): name of the parent object the template applies to (e.g. a DecisionTemplate may apply to a Loan)
  • Repeatable (Repeatability): defines how often an instance may occur per parent
    • One: (0) only one instance per parent is allowed
    • OneActive (1) only one active instance per parent is allowed
    • Many: (2) may instances per parent are allowed
  • CustomStatusList (bool): defines whether an instance has a template-driven status list
  • CustomTypeList (bool): defines whether an instance has a template-driven type list
  • ExtranetEnabled (Extranet): determins if an instance requires ObjectAccess rows added
Usage of ITemplate is baked into GenericObject's SetProperties method, allowing the following construct:


When the parameters passed to SetProperties includes Object, ObjectID and TemplateID, a SelectByTemplate statement is called, and these statements are designed to pay attention to the template table's Repeatable column and the instance table's 'active' column(s).  For instance, the ImportForm SelectByTemplate works as follows:
  • ImportFormTemplate.Repeatable = 0: if an ImportForm row based on the TemplateID exists, it is selected ("reused")
  • ImportFormTemplate.Repeatable = 1: if an ImportForm row based on the TemplateID and with no ActualCompletion date exists, it is selected ("reused")
  • ImportFormTemplate.Repeatable = 2: no existing ImportForm row will be selected, effectively creating a new row

Xslt Extensions (IXsltExtension)