In one of my apps a large chunk of the basic config data is the same but 2 fields are different depending on which client you are logged in as: the datasource and the clientSchema name. However, each client still needs the rest of that config data; so I rolled a means of supporting inheritance in my coldspring bean. Inheritance of ColdSpring defined properties as opposed to inheritance of functionality specifically.
Every configService bean I have has to extend this:
<bean id="baseConfigService" class="LB2.config.beans.baseConfigService" singleton="true">
<property name="properties">
<map>
<entry key="importDSN"><value>SpecialAccessDBDataSourcePlaceHolder</value></entry>
<entry key="rootPath"><value>C:\dev\websites\WEBSITE\PATH\</value></entry>
<entry key="relRoot"><value>/MySiteRoot/</value></entry>
<entry key="siteEmailAddress"><value>AdminEmailAddress</value></entry>
<entry key="commonSchema"><value>SHARED_SCHEMA_NAME</value></entry>
</map>
</property>
</bean>
Normally I would have to have that exact same stuff pasted into each clients config bean definition which, frankly, sucked because the paths and datasource names change depending on how the customer wants them all setup so then he had to make a bunch of duplicate edits. Not a good plan at all. Now a client specific configService bean looks like this:
<bean id="clientXConfigService" class="LB2.config.beans.configService" singleton="false">
<property name="properties">
<map>
<entry key="dsn"><value>CLIENT_DATASOURCE</value></entry>
<entry key="clientSchema"><value>CLIENT_SPECIFIC_SCHEMA</value></entry>
</map>
</property>
<property name="baseConfigService">
<ref bean="baseConfigService"/>
</property>
</bean>
Now, this might seem kind of obvious so far but really, what I want to be able to do is call my client level config service, and ask for a property that might exist in either the base service or the client service and have it return it without any of my code caring at which level the property is defined. This is taken care of through my baseConfigService.cfc and the configService.cfc.
baseConfigService.cfc
<!---
--->
<cfcomponent name="baseConfigService"
hint="Config Service API.">
<cffunction name="init" access="public" returntype="LB2.config.beans.baseConfigService" output="false"
hint="Constructor. I create a new ConfigService">
<cfset variables.properties = structnew()/>
<cfreturn this/>
</cffunction>
<cffunction name="setProperties" access="public" returntype="void" output="false"
hint="I overwrite all propertie in the configuration service">
<cfargument name="properties" type="struct" required="true" />
<cfset variables.properties = arguments.properties />
</cffunction>
<cffunction name="setProperty" access="public" returntype="void" output="false"
hint="I set a property in the configuration service">
<cfargument name="PropertyName" type="string" required="true" />
<cfargument name="PropertyValue" type="any" required="true" />
<cfset variables.properties[arguments.propertyName] = arguments.propertyValue />
</cffunction>
<cffunction name="getProperty" access="public" returntype="any" output="false"
hint="I get a property from the configuration service">
<cfargument name="PropertyName" type="string" required="true" />
<cfif structKeyExists(variables.properties,arguments.propertyName)>
<cfreturn variables.properties[arguments.propertyName]/>
<cfelse>
<cfthrow type="ConfigSerivce.PropertyNotFoundException" message="Property: #arguments.propertyName# is not known to the config service and thus cannot be retrieved." />
</cfif>
</cffunction>
<cffunction name="removeProperty" access="public" returntype="any" output="false"
hint="I remove a property from the configuration service">
<cfargument name="PropertyName" type="string" required="true" />
<cfif structKeyExists(variables.properties,arguments.propertyName)>
<cfset structDelete(variables.properties,arguments.propertyName)/>
<cfelse>
<cfthrow type="ConfigSerivce.PropertyNotFoundException" message="Property: #arguments.propertyName# is not known to the config service and thus cannot be removed." />
</cfif>
</cffunction>
</cfcomponent>
My configService cfc actually has a child object in it of type baseConfigService while also extending the baseConfigService at the same time.