My IECFUG Presentation Recording and Files

Last Friday I gave a presentation to the Inland Empire ColdFusion User Group. It covered a range of topics: MXUnit, ColdMock, and elements of my RIAForge FormUtilities and ColdSpring Bean Utilities projects.

The presentation went well, I think. There are a few technical issues towards the end when they were trying to set up a microphone to get a Q&A going, but they are minor. I've linked to the files and the recording below in case anyone is interested in having a look. Thanks again to Sami, Luis, and the IECFUG for allowing me to present!

del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 2460 Views

DynamicXMLBeanFactory and Custom FactoryBeans added to ColdSpring Utils Project

Late last night I updated the ColdSpring Bean Utilities RIAForge project. The updates include:

  • Added DynamicXMLBeanFactory: This extends the standard DefaultXMLBeanFactory but allows the ability to replace dynamic properties anywhere in the XML file, as well as in imported XML files.
  • Added MetadataAwareProxyFactoryBean: This extends the ColdSpring ProxyFactoryBean and automatically injects metadata information into any Advices that extend AbstractMetadataAwareAdvice after the AOP proxy is created.
  • Added MetadataAwareRemoteFactoryBean: This extends the ColdSpring RemoteFactoryBean and automatically injects metadata information into any Advices that extend AbstractMetadataAwareAdvice after the remote proxy is created.
  • Updated the AbstractMetadataAwareAdvice and the VOConverterAdvice for better integration with the new custom FactoryBeans.
  • Added an Examples subfolder to show these components working. A readme file is include to explain how to set it up.

The CFCs themselves all contain fairly thorough documentation in their header comments, but I'll talk briefly about some of the new components.

The new custom FactoryBeans (MetadataAwareProxyFactoryBean and MetadataAwareRemoteFactoryBean) are something of uncharted territory for me, and I'll be interested to hear what some other ColdSpring users think of how I am doing this. Basically, these extend the base ColdSpring ProxyFactoryBean and RemoteFactoryBean and contain logic to loop over the advice chain and inject metadata information into any advices that extend AbstractMetadataAwareAdvice.

Back when I first started talking about making metadata available to Advices by having ColdSpring pass the beanID of the proxied bean into the Advice, there was a lot of concern about increased coupling between the Advices and ColdSpring. I believe that the way I am using this sidesteps the issue.

My Advices are still extremely generic. All the metadata does is allow them to behave more flexibly. For example, I could create some security metadata that specifies different rules for different method calls, and a SecurityAdvice could would be able to process the correct rules for the current method call without a lot of conditional logic or actual dependence on the name of the bean or the name of the method. All it knows is that the metadata it was handed says "apply these rules now", and it does. The same could be true for a LoggingAdvice. All it would know is that the metadata being passed to it says "log these variables", and it does. The fact that you can specify different logging settings for different beans or methods is totally hidden from the Advice.

Overall I've found these new components to be very useful. I hope others agree! As always, please reply with any questions or comments. Thanks.

Comments Comments (5) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 2898 Views

Ask Brian: How to Handle Object Composition?

Christopher R contacted me through my contact form to ask about object composition. I thought I would answer it here in case it helps other folks as well. I'm also planning on answering questions like this going forward, so if anyone has questions that you think I can help with, feel free to contact me through the blog and I'll do my best to answer!

greetings...i recently came across a great article you wrote called "Write efficient code with the Composition object pattern and CFCs". it greatly assisted in my initial dilemma involving how to relate distinct but related classes. the current article works for related classes (PhoneNumber) into which you pass a final piece of data (e.g. the phone number). however, whats the best approach when that data is merely a reference or pointer (e.g. PhoneID) that requires further querying / creation of data access objects? as an example, several customers may share the same phone number (PhoneID). in this case - bear in mind that we still want to stick to OOP + not introduce db queries into the related class (e.g. PhoneID.cfc) - we might use a DAO to communicate with the related class (e.g. PhoneDAO.cfc) into which we would need to pass a database ref along with the PhoneID(s) in order to find the proper record. i would like to return a reference to the Phone object that the main class (e.g.Customer) could then utilize. to better elucidate the approach, im following a series of articles at iknowkingfoo.

hopefully this makes some sense - difficult to encapsulate in writing succintly. im getting up in arms as far as these objects, accessing their data as well as trying to access application variables. any help greatly appreciated.

thanks in advance.

To reiterate, composition models a "has-a" relationship between objects, as opposed to an "is-a" relationship which is typically done through inheritance or interface implementation. However, Christopher seems to be working with two different kinds of objects here: Singletons and business objects. How you handle the composition can depend on the kind of object you are dealing with and what they are meant to do.

For example, a PhoneDAO would almost certainly be a Singleton object, meaning that only one instance of the PhoneDAO exists in the application. However, a PhoneNumber object would be a business object, meaning that there could be many instances of PhoneNumber, each with their own data, modeling many different actual phone numbers. The same goes for Customer. Customer is a business object.

The question seems to be how to build up composite object relationships in your business objects. The answer is usually to use a Factory to build your business object. The Factory would also be a Singleton since you only need one. So Christopher might consider creating a CustomerFactory which he would call "getCustomer(13)" on to create an instance of that Customer and return it. The factory would then be responsible for also creating and setting any composite objects. As a result, the factory may itself have other singletons composed within it such as a CustomerDAO, PhoneNumberDAO, etc. The factory would use these objects and know what to do with the results (in this case, setting the resulting PhoneNumber into the resulting Customer before returning it).

The idea with factories is not only that they create objects. It has to do with the primary OO design principle of encapsulation. What the factory encapsulates is knowledge of how to create and relate a Customer and a PhoneNumber. This is crucial to understand, because it means that you become free to change how the Customer and PhoneNumber are created and related at any time. Nothing outside the factory would ever know that you made any changes.

Consider the Transfer ORM framework. Transfer handles making queries to the database as well as building object relationships for you. It is very handy, and I would recommend that Christopher have a look at it when he has the time to evaluate it. But lets say that he creates a CustomerFactory and any code that needs a user calls customerFactory.createCustomer(id). If he later decides to use Transfer, he can easily make that change because he only has to change one thing: the CustomerFactory. He can remove his own DAOs and rip out the logic that relates these objects, and replace it with calls to Transfer. Nothing outside his factory needs to know that the way these objects are being created has changed. That is the beauty and power of encapsulation, and why factories are so useful.

For building composite relationships in your Singletons, there is another option to consider: the ColdSpring framework. This framework is designed primarily to "wire up" or relate your Singleton objects. That means things like Services, DAOs, Gateways, etc. It is a really powerful tool but does have a learning curve to wrap your head around. I have a number of blog entries on ColdSpring and there are numerous other blogs and mailing lists that can help with this as well. If you give ColdSpring a look and I can offer any additional help please let me know.

Hopefully that helps, Christopher? I'd look at using a factory to handle creating and relating your objects. The factories can get rather complex if you have a lot of object relationships to manage, but again, the logic is all kept in the factories. It's certainly possible for one factory to use another factory as well, so don't feel like you have to create a single uber-factory that does everything. And if or when you decide to try out another approach such as Transfer, you'll be happy you went the factory route. Good luck!

Comments Comments (1) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 4085 Views

More on Extending ColdSpring: A Custom BeanFactory

The more I dig into how ColdSpring works the more impressed I am with it (and I was already hella impressed). I'm realizing that a lot of the utility and helper CFCs I've created and released on RIAForge can actually be implemented directly within ColdSpring by extending it.

[More]

del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 3296 Views

Extending ColdSpring Through Custom Factory Beans

Before I jumped across the pond to London and Paris last week, I had posted a blog entry about ColdSpring Remote Proxies. In response to some of the comments and IM messages, I wanted to expand on my mention of extending ColdSpring with your own Factory Beans. The ability to create your own extensions to ColdSpring is an extremely powerful technique. Unfortunately, it's also an extremely unexplained technique! I hope to change that a bit, so let's get to it.

If you aren't familiar with ColdSpring's ability to automatically generate Remote Proxy components, I'll refer you to a few blog entries:

In a nutshell, ColdSpring can create remote proxy CFCs for your actual underlying CFCs, typically service layer components. Which is pretty darn sweet. Unfortunately, the configuration XML to do this can get rather verbose, especially if you want to create numerous proxies. Consider:

<bean id="remoteUserService" class="coldspring.aop.framework.RemoteFactoryBean">
	<property name="target">
		<ref bean="userService" />
	</property>
	<property name="beanFactoryScope">
		<value>application</value>
	</property>        
	<property name="beanFactoryName">
		<value>beanFactory</value>
	</property>    
	<!--- Physical name given to the proxy component --->
	<property name="serviceName">
		<value>RemoteUserService</value>
	</property>
	<!--- location to the physical proxy component --->
	<property name="relativePath">
		<value>/remote</value>
	</property>
	<!--- you could have something like get* for all get methods only --->
	<property name="remoteMethodNames">
		<value>*</value>
	</property>
</bean>
		

It seems like a lot, and I suppose it is. The good news is that you only have to do it one time, at the start of your project. Still, my previous blog entry showed that you can trim this down a bit, especially if you are creating more than one remote proxy:

<!--- Create a parent bean that all concrete remote proxies to extend, which reduces the XML for the child beans. --->
<bean id="abstractRemoteProxy" class="" abstract="true">
	<property name="beanFactoryScope">
		<value>application</value>
	</property>
	<property name="beanFactoryName">
		<value>beanFactory</value>
	</property>
	<!--- location to the physical proxy component --->
	<property name="relativePath">
		<value>/remote</value>
	</property>
</bean>

<!--- Concrete bean extends the abstract parent bean. --->
<bean id="remoteUserService" class="coldspring.aop.framework.RemoteFactoryBean" parent="abstractRemoteProxy" lazy-init="false">
	<property name="target">
		<ref bean="userService" />
	</property>
	<!--- Physical name given to the proxy component --->
	<property name="serviceName">
		<value>RemoteUserService</value>
	</property>
	<!--- you could have something like get* for all get methods only --->
	<property name="remoteMethodNames">
		<value>*</value>
	</property>
</bean>
		

Better, but I still think we can improve on it. But this is where we go into potentially scary territory: we're going to extend ColdSpring to make our lives easier. In this case, I'm going to create my own custom Remote Factory Bean that extends ColdSpring's RemoteFactoryBean and sets up some default values that I tend to use over and over in my applications. This reduces the XML configuration even further, but still allows me to override the defaults if I need to. Here is the XML:

<bean id="abstractRemoteProxy" class="" abstract="true">
	<property name="relativePath">
		<value>/remote</value>
	</property>
</bean>

<bean id="remoteUserService" class="factory.CustomRemoteFactoryBean" parent="abstractRemoteProxy" lazy-init="false">
	<property name="targetBeanID">
		<value>UserService</value>
	</property>
	<property name="remoteMethodNames">
		<value>*</value>
	</property>
</bean>
		

Hmm, that's quite a bit shorter! You'll notice that my RemoteUserService is specifying it's class as "CustomRemoteFactoryBean". That's the first change. You may also notice that many of the properties are gone, but a new one has appeared: "targetBeanID". By passing the targetBeanID to my custom factory bean, I can set up a series of default property values due to the fact that my remote proxies tend to follow a fairly standard setup. Here is the code for the CustomRemoteFactoryBean to demonstrate what it is doing:

<cfcomponent name="CustomRemoteFactoryBean" extends="coldspring.aop.framework.RemoteFactoryBean" hint="I add custom behavior to Remote Factory Beans.">
	
	<cffunction name="init" access="public" returntype="any" hint="Constructor.">
		<cfset super.init() />
		<cfreturn this />
	</cffunction>
	
	<cffunction name="getObject" access="public" returntype="any" output="true">
		<cfset var local = StructNew() />
		
		<!--- If the current bean is not constructed, set default values. --->
		<cfif not isConstructed()>
		
			<!--- Default the service name to the name of the target bean ID with 'Remote' appended to the front of it. --->
			<cfif not StructKeyExists(variables, 'serviceName') or not Len(variables.serviceName)>
				<cfset setServiceName('Remote#getTargetBeanID()#') />
			</cfif>
			
			<!--- Set the target to the bean referenced by the target bean ID. --->
			<cfif not StructKeyExists(variables, 'target') or not IsObject(variables.target)>
				<cfset setTarget(getBeanFactory().getBean(getTargetBeanID())) />
			</cfif>
			
			<!--- Set default Bean Factory Name. --->
			<cfif not StructKeyExists(variables, 'beanFactoryName') or not Len(variables.beanFactoryName)>
				<cfset setBeanFactoryName('beanFactory') />
			</cfif>
			
			<!--- Set default Bean Factory Scope. --->
			<cfif not StructKeyExists(variables, 'beanFactoryScope') or not Len(variables.beanFactoryScope)>
				<cfset setBeanFactoryScope('application') />
			</cfif>
			
		</cfif>
		<cfset local.object = super.getObject() />
		<cfreturn local.object />
	</cffunction>
	
	<cffunction name="getTargetBeanID" access="public" returntype="string" output="false" hint="I return the Target Bean ID.">
		<cfreturn variables['targetBeanID'] />
	</cffunction>
		
	<cffunction name="setTargetBeanID" access="public" returntype="void" output="false" hint="I set the Target Bean ID.">
		<cfargument name="targetBeanID" type="string" required="true" hint="TargetBeanID" />
		<cfset variables['targetBeanID'] = arguments.targetBeanID />
	</cffunction>
	
</cfcomponent>
		

The CustomRemoteFactoryBean extends the ColdSpring RemoteFactoryBean and adds additional behavior. If you weren't aware, under the hood ColdSpring calls getObject() on the RemoteFactoryBean when it needs to create an instance of your remote proxy. You can see that my getObject() method is automatically setting up default values for the service name, target, bean factory name, and bean factory scope if these are not defined. Then it simply calls the superclass's getObject() method to actually create the remote proxy. This is how I can get away with specifying so little in the XML.

Your first reaction might be "OK that's kind of cool because I hate typing XML, but is that really it?" Yes, that is it! For this blog entry anyway, since it's gotten rather long. But if people want me to keep going I can expand further. In the meantime, you might start thinking about what sort of behavior you can add to your own custom getObject() method that adds behavior beyond defining simple default values. And please fire away with thoughts or comments!

Comments Comments (1) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 2885 Views

Previous Entries / More Entries