Monday, October 19, 2009

ColdFusion 9 Oddities

I ran into a couple interesting things when playing around with ColdFusion 9 today.

Oddity #1:
I was trying to create a really simple User entity using ORM.

User.cfc

<cfcomponent persistent="true">

<cfproperty name="id" fieldtype="id" generator="native" />
<cfproperty name="firstName" />
<cfproperty name="lastName" />
<cfproperty name="isDeleted" type="boolean" />
<cfproperty name="createdOn" type="date" />

</cfcomponent>


Here's what a dump of the User looks like:



I realized that I typically put isDeleted and createdOn on all of my entities, so I decided I would put them on a base class, Entity.cfc, that my User entity could extend. Here's the updated components:

User.cfc

<cfcomponent persistent="true" extends="Entity">

<cfproperty name="id" fieldtype="id" generator="native" />
<cfproperty name="firstName" />
<cfproperty name="lastName" />

</cfcomponent>


Entity.cfc

<cfcomponent>

<cfproperty name="isDeleted" type="boolean" />
<cfproperty name="createdOn" type="date" />

</cfcomponent>


However, when I went to look at my User, I noticed the extended properties were missing.



After a little while, I tried adding accessors="true" to my Entity base class. It seems slightly odd to need to add that since the parent object is persistent, but it gave me my getters and setters back.

Entity.cfc

<cfcomponent accessors="true">

<cfproperty name="isDeleted" type="boolean" />
<cfproperty name="createdOn" type="date" />

</cfcomponent>


And here's the result:



All good, right? Unfortunately not. I tried executing the following code:

index.cfm

<cfset user = EntityNew("User") />

<cfset user.setFirstName("Tony") />
<cfset user.setLastName("Nelson") />
<cfset user.setIsDeleted(0) />
<cfset user.setCreatedOn(now()) />

<cfset EntitySave(user) />


While this appeared to work in the interface. when I took a peak at the database, it didn't save my isDeleted or createdOn values. In fact, it didn't even create the columns in the database.

I decided to check out what Hibernate was doing by setting this.ormSettings.saveMapping = true in my Application.cfc. Here's the auto-generated User.hbmxml:

User.hbmxml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class entity-name="User" lazy="true" name="cfc:cat.User" table="`User`">
<id name="id" type="int">
<column name="id"/>
<generator class="native"/>
</id>
<property name="firstName" type="string">
<column name="firstName"/>
</property>
<property name="lastName" type="string">
<column name="lastName"/>
</property>
</class>
</hibernate-mapping>


Apparently Hibernate wasn't able to pick up any properties defined in my base Entity.cfc. To solve this, I simply manually added the properties to the hibernate mapping file like such:

User.hbmxml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class entity-name="User" lazy="true" name="cfc:cat.User" table="`User`">
<id name="id" type="int">
<column length="10" name="id"/>
<generator class="native"/>
</id>
<property name="firstName" type="string">
<column length="255" name="firstName"/>
</property>
<property name="lastName" type="string">
<column length="255" name="lastName"/>
</property>
<property name="isDeleted" type="boolean">
<column name="isDeleted"/>
</property>
<property name="createdOn" type="date">
<column name="createdOn"/>
</property>
</class>
</hibernate-mapping>


This seemed to do the trick and everything was happy once again. I guess I'll be using the mapping files more than I had originally planned.

Oddity #2:
It appears that using ColdFusion mixins inside CFCs no longer works in CF9. Take the following really basic example:

User.cfc

<cfcomponent>

<cfinclude template="mixin.cfm" />

</cfcomponent>


mixin.cfm

<cffunction name="sayHello">

<cfreturn "Hello, world" />

</cffunction>


I could then create a new User like so:

index.cfm

<cfset user = createObject("component","User") />

<cfdump var="#user#" />


If I were to run this code in CF8, I would get a User that looked like:



However in CF9, I get a completely empty User object:



Odd. Yeah it's not a very common use-case, but it's still something that can come in handy every now and then.

UPDATE: Apparently mixins still work, they just don't appear when you dump the component.

No comments:

Post a Comment