B. Developing New Connectors
- John Willis
iMumpsConnector Interface
CFMumps is a highly modular, orthogonal system: the Global API (lib.cfmumps.global) calls into the Basic API (lib.cfmumps.mumps), which in turn calls into the default connector configured in cfmumps.ini. Thus, lib.cfmumps.mumps is a wrapper, which simply passes the parameters of its component methods to the underlying connector.
In order for this architecture to work, CFMumps takes advantage of CF interfaces, which are essentially object-oriented blueprints, setting forth a set of methods and their parameters which a component must contain in order to implement the interface.
The CFMumps connectors all implement the iMumpsConnector interface, which essentially requires the connector to implement the CFMumps Basic API.
Below is the iMumpsConnector interface:
<cfinterface> <cffunction name="open" returntype="component" access="public" output="false"/> <cffunction name="isOpen" returntype="boolean" access="public" output="false"/> <cffunction name="close" returntype="component" access="public" output="false"/> <cffunction name="getSettings" returntype="void" access="public" output="true"/> <cffunction name="saveSettings" returntype="void" access="public" output="true"/> <cffunction name="set" returntype="void" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> <cfargument name="value" type="string" required="true"> </cffunction> <cffunction name="get" returntype="any" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="kill" returntype="void" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="data" returntype="struct" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="order" returntype="struct" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="mquery" returntype="string" access="public" output="false"> <cfargument name="globalRef" type="string" required="true"> </cffunction> <cffunction name="merge" returntype="numeric" access="public" output="false"> <cfargument name="inputGlobalName" type="string" required="true"> <cfargument name="inputGlobalSubscripts" type="array" required="true"> <cfargument name="outputGlobalName" type="string" required="true"> <cfargument name="outputGlobalSubscripts" type="array" required="true"> </cffunction> <cffunction name="lock" returntype="boolean" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> <cfargument name="timeout" type="numeric" required="true" default="0"> </cffunction> <cffunction name="unlock" returntype="boolean" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="mVersion" returntype="string" access="public" output="false"/> <cffunction name="mFunction" returntype="any" access="public" output="false"> <cfargument name="fn" type="string" required="true"> <cfargument name="args" type="array" required="true"> </cffunction> </cfinterface>
Functional Requirements
In order for a CFMumps connector to give reliable and robust performance, it must adhere to the following requirements:
- All CFMumps connectors must implement the iMumpsConnector interface
- CFMumps connectors should not use vendor-specific extensions, and should aim for compatibility with Adobe ColdFusion 10
- CFMumps connector methods should never rely on variables existing outside of their component's scope, and should never assume that session management is available
- CFMumps connector methods should use function-local variables when possible
- CFMumps connectors should assume that they will be called concurrently by multiple, simultaneous threads, and as such, should use <cflock> or other such tools to avoid concurrency problems.
- CFMumps connectors should extend lib.cfmumps.admin and use its getConfig() and setConfig() methods to store connector-specific settings. Under no circumstances should a CFMumps connector ever access cfmumps.ini directly, as Coherent Logic Development reserves the right to change the entire configuration storage mechanism at any time, and the getConfig() and setConfig() APIs will always be kept up to date with the latest mechanisms.
- CFMumps connectors should implement proper namespacing for forms exposed by their getSettings() methods, as they will be included in tabs within the CFMumps Administrator application
- Must expose the connectorName and connectorVersion member variables for proper CFMumps Administrator functionality
- No API exposed when implementing the iMumpsConnector interface should rely on MUMPS global data, nor should any of your APIs have any database-related side effects beyond what would normally be expected for the operation being implemented.
Connector Template
The following template gives you a starting point for implementing your own connector.
<cfcomponent output="false" implements="iMumpsConnector" extends="lib.cfmumps.admin"> <cfset this.connectorName = "My Connector"> <cfset this.connectorVersion = "0.01"> <cfset this.connectorPath = "lib.cfmumps.<this-connector-name>"> <cfset this.someSetting = this.getConfig(this.connectorPath, "someSetting")> <cffunction name="open" returntype="component" access="public" output="false"> </cffunction> <cffunction name="isOpen" returntype="boolean" access="public" output="false"> </cffunction> <cffunction name="close" returntype="component" access="public" output="false"> </cffunction> <cffunction name="getSettings" returntype="void" access="public" output="true"> </cffunction> <cffunction name="saveSettings" returntype="void" access="public" output="true"> </cffunction> <cffunction name="set" returntype="void" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> <cfargument name="value" type="string" required="true"> </cffunction> <cffunction name="get" returntype="any" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="kill" returntype="void" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="data" returntype="struct" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="order" returntype="struct" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="mquery" returntype="string" access="public" output="false"> <cfargument name="globalRef" type="string" required="true"> </cffunction> <cffunction name="merge" returntype="numeric" access="public" output="false"> <cfargument name="inputGlobalName" type="string" required="true"> <cfargument name="inputGlobalSubscripts" type="array" required="true"> <cfargument name="outputGlobalName" type="string" required="true"> <cfargument name="outputGlobalSubscripts" type="array" required="true"> </cffunction> <cffunction name="lock" returntype="boolean" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> <cfargument name="timeout" type="numeric" required="true" default="0"> </cffunction> <cffunction name="unlock" returntype="boolean" access="public" output="false"> <cfargument name="globalName" type="string" required="true"> <cfargument name="subscripts" type="array" required="true"> </cffunction> <cffunction name="mVersion" returntype="string" access="public" output="false"> </cffunction> <cffunction name="mFunction" returntype="any" access="public" output="false"> <cfargument name="fn" type="string" required="true"> <cfargument name="args" type="array" required="true"> </cffunction> </cfcomponent>
See Also