Local createData() is bypassed in FarCry

Hi there,

I’m having an issue overwriting the default createData() function for types.

Can you please clarify if createData() is still supported in FarCry edit handler? Below is an example code that I’ve used to overwrite the types createData() function to perform additional business logic for my custom data type when a new record is created inside FarCry. However, it doesn’t seem to execute this function as it just by-pass the cfdump and cfabort. If I add a dump and abort in farcry.core.package.types.types createData() function that works!


<cfcomponent extends="farcry.core.packages.types.types" displayname="Workshop subscription cancellation log" bFriendly="false" bAudit="false" bRefObjects="false">

	<cfproperty name="workshopId" type="uuid" required="no" default="" ftlabel="Workshop" ftJoin="mecWorkshop">

	<cffunction name="createData" access="public" returntype="any" output="true" hint="Creates an instance of an object">
		<cfargument name="stProperties" type="struct" required="true" hint="Structure of properties for the new object instance">
		<cfargument name="user" type="string" required="true" hint="Username for object creator" default="">
		<cfargument name="auditNote" type="string" required="true" hint="Note for audit trail" default="Created">
		<cfargument name="dsn" required="No" default="#application.dsn#">
		<cfargument name="bAudit" type="boolean" default="true" required="false" hint="Set to false to disable logging" />

		<cfdump var="#arguments#" label="local createData" /><cfabort>

		<cfreturn super.createData(argumentCollection="#arguments#") />



createData() and setData() would only be overridden in exceptional circumstances. You will have a much better time working with beforeSave() and afterSave().

Hi @modius

Thanks for your speedy response.
I can work with beforeSave() and afterSave(). Is there any a way I can tell if the save is for a new record or existing record?

Hmm… I’ve never needed to know that for any existing projects, but my guess would be maybe something like the following (there is probably a better “FarCry” way to do it though =) )

Note: I have not tested this.

if (stProperties.dateTimeCreated eq stProperties.dateTimeLastUpdated) {
  /* New Record */
} else {
  /* Existing record */

Oh yes that would work! Thanks @jeff
If anyone has a “Farcry” way to do it, happy to know as well :smile:

Hi @modius

I noticed that calling createData() (when creating objects outside of FarCry) doesn’t execute my local version of beforeSave() and afterSave(), only setData() would execute those 2 functions. Can you please explain why this is the case and it is compulsory to call setData() after a createdData()?


That problem has been in FarCry a very long time. Most of us have given up on a fix and just make sure to call beforeSave() and afterSave() manually when using createData().

Neither setData nor createData will call beforeSave. You need to call it yourself prior to those calls. setData does call afterSave if you leave the bAfterSave argument set to true. createData does not call afterSave. You must call it manually. If you use the formtools library to save your items, the framework handles this for you, however if you script your own data manipulation then you need to call the entire workflow manually.

Its unfortunate that the inconsistency exists (setData and createData working differently) but having them separate does allow you more freedom where if you are scripting an import perhaps you don’t want to call beforeSave or afterSave for some reason. The framework allows you to bypass those if you need.

That’s right, createData() just does the insert, it has no other functionality… If you need to run beforeSave() or afterSave() for some reason then you can call them manually.

You don’t need to call both createData() and setData(), you can just call setData() by itself. It will do an “upsert”, so if the record doesn’t exist it will be inserted, and if the record does exist then it will be updated. As mentioned, setData() also calls afterSave() so you don’t need to call it manually.