Photo from Chile

A Recursive Function to Gather CFC Metadata for Inherited Properties

Charlie Stell made a comment on my last post about my Base Persistent Object project, pointing out that my populate method did not take inherited properties into account. When I first developed it I wasn't using inheritance with ColdFusion ORM, as I'm coming from a Transfer background and Transfer doesn't really support inheritance. On a recent project using CF ORM I did implement an inheritance scheme and decided to update my populate method to support that.

The reason that the current populate method does not support inheritance is that is simply looks at the properties array that is included in the cfc metadata of the current object. That array of properties does not include any inherited properties. To find those you need to look at the extends key in the metadata structure and check for any properties of the object that the current object extends, and, of course any objects that that extends, etc. You could potentially have several levels of parents as you move up the inheritance hierarchy.

I decided that the best approach would be to write a recursive function that would return all of the properties of an object as an array, including all properties of any of the object's parents. In his comment Charlie provided some sample code that he is using, and I took his suggestion and made a couple of changes to it. Here's the code:

view plain print about
1private array function collectAllProperties(required struct md,array props=ArrayNew(1)) {
2    local.prop = 1;
3    if (structKeyExists(arguments.md,"properties")) {
4        for (local.prop=1; local.prop <= ArrayLen(arguments.md.properties); local.prop++) {
5            if (not ArrayContains(arguments.props,arguments.md.properties[local.prop].name)) {
6                arrayAppend(arguments.props,arguments.md.properties[local.prop]);
7            }
8        }
9    }
10    if (arguments.md.extends.fullname neq "WEB-INF.cftags.component") {
11        arguments.props = collectAllProperties(arguments.md.extends,arguments.props);
12    }
13    return arguments.props;
14}

To use this function, you simply pass in the metadata of an object into the md argument, so if I wanted to get the metadata for all properties for a User object I would do something like:

view plain print about
1User = EntityNew("User");
2userProperties = collectAllProperties(getMetadata(User));

[More]

Simple Base Persistent (ORM) Object for CF9 Now Available

I mentioned in an earlier blog post that I've been working on a Base Persistent Object (BPO) for ColdFusion 9 that can be extended by other components to provide them with certain behaviours. In order to add the kind of flexible behaviour that I desire in my BPO, I compose a number of other objects into it, which it then uses to accomplish things such as automatic validation and returning population and validation failures to whomever called its methods. I realized as I was preparing it for public consumption that it is a much larger task that I first envisioned to document and describe all of its intricacies and dependencies. I have decided, therefore to start by releasing a Simple Base Persistent Object, which can be used as a standalone object. It does not accomplish all that my full-featured BPO does, but it works as is, and will hopefully provide some ideas for what a BPO can do and how a BPO can be used.

For those who want to skip the explanation and just see the code, it can be downloaded from the Base Persistent Object RIAForge Project.

[More]

A Base Persistent (ORM) Object for CF9

I've been doing some experimentation with ColdFusion 9's Hibernate (ORM) integration, part of which involved creating a Base Persistent Object.

What is a Base Persistent Object?

I'm using the term persistent object to refer to a ColdFusion 9 cfc that has a persistent="true" attribute. That is, a component that is used to create objects that will be persisted to a database via Hibernate, using CF9's ORM integration. These are variously referred to as persistent objects, ORM objects, entity objects, etc. There are certain behaviours that I want all of my persistent objects to have, and I have found that the best way to achieve this is to create a base persistent object and then have all of my concrete persistent objects extend that base object.

Behaviours contained in the Base Persistent Object

The behaviours that I'm including in my Base Persistent Object allow any object that extends it to:

  • populate itself from user-submitted data
  • save itself
  • delete itself
  • validate itself
  • inject dependencies into itself via Coldspring

As CF9 is still in beta, this object is obviously in flux. I am planning on releasing the code for the object as open source, and have set up a project at BasePersistentObject.riaforge.org for that purpose. I hope to have a 0.1 version available shortly, at which point the code will be available for download via the project page.