How do I use the MachII.util.UtilityConnector to leverage caching and logging within ColdSpring or other bean factories?

By Peter J. Farrell (peter@…)

The MachII.util.UtilityConnector is a helper component that allows you to leverage your already configured caching and logging subsystems within your model layer. Both the caching and logging packages are cross-cutting subsystems in the MVC stack and have been designed to be utilized outside of Mach-II's MVC architecture. Since these packages are agnostic from the Mach-II MVC layer, using them in your model layer does not create any coupling to the Mach-II MVC layer because you could remove the the Mach-II MVC layer from your application and load your logging and/or caching in another manner. Mach-II is using Mach-II specific loaders (MachII.logging.LoggingProperty and MachII.caching.CachingProperty) to load these packages in the context of Mach-II. Loading these packages outside of the context of Mach-II would amount to trivial code.

The following example connects Mach-II managed logging and caching subsystems for use in ColdSpring.

Setting up the UtilityConnector

Define UtilityConnector bean defintion:

<bean id="utilityConnector"
	class="MachII.util.UtilityConnector"/>

You must be using the ColdspringProperty that is located at MachII.properties.ColdspringProperty for the UtilityConnector to function. Otherwise you will get an exception similar to:

Cannot find the temporary AppManager reference in request._MachIIAppManager.
Please be sure that you are using the ColdspringProperty located in 'MachII.properties.ColdspringProperty'.

Using the Logging Package

We are assuming that you have setup and defined some loggers in your Mach-II configuration file using the MachII.logging.LoggingProperty.

Define LogFactory bean definition:

<bean id="logFactory"
	factory-bean="utilityConnector"
	factory-method="getLogFactory" />

Getting a log into a ColdSpring managed bean

Option 1

This option allows you dynamically set the channel name into the log.

<bean id="someBean"
	type="dot.path.to.SomeBean">
	<property name="log"><ref bean="logFactory"/></property>
</bean>

In your dot.path.to.SomeBean, you need to get a log from the LogFactory and set the channel into it before you can use it to log messages:

<cffunction name="setLog" access="public" returntype="void" output="false"
	hint="Uses the log factory to create a log.">
	<cfargument name="logFactory" type="MachII.logging.LogFactory" required="true" />
	<!--- Get the channel name dynamically by using the CFC metadata --->
	<cfset variables.log = arguments.logFactory.getLog(getMetadata(this).name) />
</cffunction>
<cffunction name="getLog" access="public" returntype="MachII.logging.Log" output="false"
	hint="Gets the log.">
	<cfreturn variables.log />
</cffunction>

As demonstrated in the code above, we are dynamically getting the full dot path to the CFC via the CFC's metadata using getMetadata(this).name. If a difference channel name is required, this could easily be replaced with other logic.

Option 2

This option forces you to hard code the channel name in your ColdSpring configuration file.

<bean id="someBean"
	type="dot.path.to.SomeBean">
	<property name="log">
		<bean factory-bean="logFactory" factory-method="getLog">
			<constructor-arg name="channel"><value>Cart</value></constructor-arg>
		</bean>
	</property>
</bean>

In your dot.path.to.SomeBean add a getter/setter for the log:

<cffunction name="setLog" access="public" returntype="void" output="false"
	hint="Set the log.">
	<cfargument name="log" type="MachII.logging.Log" required="true" />
	<cfset variables.log = arguments.log />
</cffunction>
<cffunction name="getLog" access="public" returntype="MachII.logging.Log" output="false"
	hint="Gets the log.">
	<cfreturn variables.log />
</cffunction>

Using a log

Now you can call getLog() to get the now configured log and begin logging:

<cfif getLog().isDebugEnabled()>
   <!--- Logic to do something --->
   <cfset getLog().debug("I set something into some scope which indicates I completed some action") />
</cfif>

<cftry>
   <cfset set[a] = b />
   <cfcatch type="any">
      <cfset getLog().error("Something bad happened and I'm going to pass in the cfcatch as well", cfcatch) />
   </cfcatch>
</cftry>

Using the Caching Package

This allows you to get a cache strategy that is already configured by the MachII.caching.CachingProperty in your Mach-II configuration file.

Getting a cache strategy into ColdSpring managed bean

Option 1

Define a CacheStrategyManager bean definition:

<bean id="cacheStrategyManager"
	factory-bean="utilityConnector"
	factory-method="getCacheStrategyManager" />

Set a cache named 'products' to a ColdSpring managed bean:

<bean id="someBean"
	type="dot.path.to.SomeBean">
	<property name="cache">
		<bean factory-bean="cacheStrategyManager" factory-method="getCacheStrategyByName">
			<constructor-arg name="cacheStrategyName"><value>products</value></constructor-arg>
		</bean>
	</property>
</bean>

Option 2

You can setup your own caching strategies to be injected into your target bean, however these strategies will not be managed by the CacheStrategyManager and will not show up in the Mach-II dashboard application.

In your target bean

In your dot.path.to.SomeBean add a getter/setter for the cache strategy:

<cffunction name="setCache" access="public" returntype="void" output="false"
	hint="Set a cache.">
	<cfargument name="cache" type="MachII.caching.strategies.AbstractCacheStrategy" required="true" />
	<cfset variables.cache = arguments.cache />
</cffunction>
<cffunction name="getCache" access="public" returntype="MachII.caching.strategies.AbstractCacheStrategy" output="false"
	hint="Gets the cache.">
	<cfreturn variables.cache />
</cffunction>

Using the cache strategy

Now you can use the cache strategy within your ColdSpring managed bean. See the cache strategy API for more information on using cache strategies.

Warnings

  • Do not inject the UtilityConnector into beans, use the 'factory' like methods instead.

Back to FAQs