Coldfusion Zeus (10 Beta) Function Expressions and Closures Not Quite There

Bug reported https://bugbase.adobe.com/index.cfm?event=bug&id=3120695

So I was playing with Coldfusion 10 Beta and was trying to do some of the things I am used to in Javascript. When I came upon this issue.

<cfscript>
test={
	one="1"
	, two=function(){ return "2" }
};
</cfscript>
<cfoutput>#test.two()#</cfoutput>

Error

Invalid CFML construct found on line 2 at column 6
ColdFusion was looking at the following text:
{
. . . blah blah blah

What I would expect is to get the number two written to the page, but apparently you cannot define the function inline. But you can predefine the function.

<cfscript>
two=function(){ return "2"; };
test={
	one="1"
	, two=two
};
</cfscript>
<cfoutput>#test.two()#</cfoutput>

In a hacky workaround, you can create a function which returns a function expression.

<cfscript>
func=function(f){ return f; };
test={
one="1"
, two=func(function(){ return "2"; })
};
</cfscript>
<cfoutput>#test.two()#</cfoutput>

Similarly I also was not able to call the this scope inside a passed in function expression using the invoke command.

Bug reported https://bugbase.adobe.com/index.cfm?event=bug&id=3120773

Test.cfc

component {
	instance.options={};
	function init(options) {
		StructAppend(instance.options, options, false);
		return this;
	}

	function call(option, args={}) {
		return invoke(instance.options, option, args);
	}
}

Test.cfm (Works)

<cfscript>
two=function(){ return arguments; };
test=new Test({
	one="1"
	, two=two
});
</cfscript>
<cfdump var="#test.call("two", {three=3})#" />

Test.cfm (Works)

<cfscript>
two=function(){ return this; };
test=new Test({
	one="1"
	, two=two
});
test.two=two;
</cfscript>
<cfdump var="#test.two()#" />

Test.cfm (Doesn’t Works)

<cfscript>
two=function(){ return this; };
test=new Test({
	one="1"
	, two=two
});
</cfscript>
<cfdump var="#test.call("two", {three=3})#" />

Error

Variable THIS is undefined

Thanks to Ben Nadel’s well timed post for helping me understand more about this.

http://www.bennadel.com/blog/2334-ColdFusion-10-Beta-Closures-And-Components-And-The-THIS-Scope.htm

And to Raymond Camden for pointing me to it and encouraging me to post bug reports.

If I have made an error here could anyone please correct me?

Thoughts on Coldfusion Codename Zeus (v10 I assume)

I watched this presentation by Rakshith Naresh and here are some things I am excited about:

  • Function enhancements, closures, anonymous functions.  It’s Coldfusion, so I am assuming that there will be something wrong with them this next version (just like their implicit structures and arrays), which makes me sad, but by CF11 they should be functional.  But I am crossing my fingers that they will pull this off.
  • Java enhancements, per application JAR path an java settings will be awesome.  I will finally be able to stop worrying about JavaLoader and any memory leaks that it comes with.
  • Websockets, while this is still future tech, I am excited that Coldfusion will make websockets relatively easy to take advantage of.
  • CFCHART enhancements, adding SVG/Canvas support along with javascript hooks will make CFCHART much more reasonable to work with.
  • Caching, I don’t know much about what it will be, but it seems that they are going in the right direction.  The ability to run a cache server in a separate process sounds nifty.
  • Server update management, waaaayyy overdue.  I mean finally a simple way for Coldfusion to know if it is out of date.  Includes Hotfixes =]
  • Better Scheduled Tasks, scheduled tasks is such a pain in the ass, hopefully the new engine will give more flexibility.
  • FTP as a virtual file system, this has the potential to help immensely for managing uploaded files to a separate server.
  • CFScript improvements, for…in for queries and lists.  This just makes sense.

I am especially excited for the closures.  I think that feature will change everything about using Coldfusion for me.  Lets all welcome Coldfusion to the 21st century.

Using Freemarker in Coldfusion

It was quite a pain trying to find a decent template system to use in Coldfusion.  I finally landed on Freemarker, because I had used it’s syntax before.  I had to jump through some hurdles to finally figure out how to effectively use it, so here I will share how I did it.

Download JavaLoader:
http://javaloader.riaforge.org/

Download Freemarker:
http://freemarker.sourceforge.net/freemarkerdownload.html

I use JavaLoader because I do not always have control over the Coldfusion environment that my applications will run on.

Here is the cfc

<cfcomponent name="FreeMarker" output="no">

<cfscript>
instance=StructNew();
instance.ID=CreateUUID();
instance.Out=createObject("java", "java.io.StringWriter").init();
instance.Map=StructNew();
instance.JavaLoader="";
</cfscript>

<cffunction name="init" hint="Constructor" access="public" returntype="FreeMarker" output="false">
 <cfargument name="JavaLoader" type="any" required="yes">

 <cfscript>
 instance.JavaLoader=arguments.JavaLoader;
 </cfscript>

 <cfreturn this />
</cffunction>

<cffunction name="setContent" access="public" returntype="FreeMarker" output="false">
 <cfargument name="Template" type="string" required="yes">
 <cfscript>
 instance.Content=createObject("java", "java.io.StringReader").init(arguments.Template);
 instance.Template=instance.JavaLoader.create("freemarker.template.Template").init("FMT_" & instance.ID, instance.Content);
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="process" access="public" returntype="string" output="false">
 <cfscript>
 instance.Template.process(instance.Map, instance.Out);
 instance.Out.flush();
 </cfscript>
 <cfreturn instance.Out.toString() />
</cffunction>

<cffunction name="putInt" access="public" returntype="FreeMarker" output="false">
 <cfargument name="name" type="string" required="true" />
 <cfargument name="in" type="numeric" required="true" />
 <cfscript>
 instance.Map[arguments.name]=JavaCast("int", arguments.in);
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="putString" access="public" returntype="FreeMarker" output="false">
 <cfargument name="name" type="string" required="true" />
 <cfargument name="in" type="string" required="true" />
 <cfscript>
 instance.Map[arguments.name]=JavaCast("string", arguments.in);
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="putArray" access="public" returntype="FreeMarker" output="false">
 <cfargument name="name" type="string" required="true" />
 <cfargument name="in" type="array" required="true" />
 <cfscript>
 instance.Map[arguments.name]=arguments.in;
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="putStruct" access="public" returntype="FreeMarker" output="false">
 <cfargument name="name" type="string" required="true" />
 <cfargument name="in" type="struct" required="true" />
 <cfscript>
 instance.Map[arguments.name]=arguments.in;
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="putQuery" access="public" returntype="FreeMarker" output="false">
 <cfargument name="name" type="string" required="true" />
 <cfargument name="in" type="query" required="true" />
 <cfscript>
 instance.Map[arguments.name]=QueryToArray(arguments.in);
 </cfscript>
 <cfreturn this />
</cffunction>

<cffunction name="getMap" access="public" returntype="struct" output="false">
 <cfreturn instance.Map />
</cffunction>

<!--- ===================================== --->

<!--- Got from Ben Nadel: http://www.bennadel.com/blog/124-Ask-Ben-Converting-a-Query-to-an-Array.htm --->
<cffunction name="QueryToArray" access="private" returntype="array" output="false"
 hint="This turns a query into an array of structures.">

 <!--- Define arguments. --->
 <cfargument name="Data" type="query" required="yes" />

 <cfscript>
 // Define the local scope.
 var LOCAL = StructNew();
 // Get the column names as an array.
 LOCAL.Columns = ListToArray( ARGUMENTS.Data.ColumnList );
 // Create an array that will hold the query equivalent.
 LOCAL.QueryArray = ArrayNew( 1 );
 // Loop over the query.
 for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount ; LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
 // Create a row structure.
 LOCAL.Row = StructNew();
 // Loop over the columns in this row.
 for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen( LOCAL.Columns ) ; LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
 // Get a reference to the query column.
 LOCAL.ColumnName = LOCAL.Columns[ LOCAL.ColumnIndex ];
 // Store the query cell value into the struct by key.
 LOCAL.Row[ LOCAL.ColumnName ] = ARGUMENTS.Data[ LOCAL.ColumnName ][ LOCAL.RowIndex ];
 }
 // Add the structure to the query array.
 ArrayAppend( LOCAL.QueryArray, LOCAL.Row );
 }
 // Return the array equivalent.
 return( LOCAL.QueryArray );
 </cfscript>
</cffunction>

</cfcomponent>

Download the full example here

AlanClendenin.com Launched

Well, a much overdue update to my father’s website has been completed. AlanClendenin.com has been launched on GSL Solutions’ FrontRunner CMS.  Check it out, I’m rather proud of it.

It’s the perfect communication tool for my father, who is politically active and needed a website to publish not only blog posts, but also news items.

I’m pretty much using his website as my test bed for new features and ideas.  Plus who better to suggest features than a family member.

You know how family is with software.  They are always asking “Can I do …”, or “How do I …”.

I would like to thank Flip who designed the website.

Thoughts on CMS’s as Version Control Systems

I got myself to thinking about versioning content in a content management system.  It seems to me that when it comes down to it versioning of content is integral to the success of long term usability of a CMS.  As any website grows more and more users will need to have access to both create and maintain the content of a website.  But I was thinking that version control can server a better purpose then just helping with workflow.

Let’s apprise one of the weaknesses of the internet, permanence.  After I post this article on my website, the website would seem to be the same website, but looking at it from a different perspective you could consider it to be a “new edition”.  Much like a book, adding new information and reprinting it, you would have a new book as a different edition.  The problem with this analogy is that with books you can take the two editions and compare them side by side, but with a website the old edition is gone forever (kind of).  Comparing two editions of a book can show you exactly what changes have been made, while there is no way of knowing exactly what has changed on a website.

Now this is not entirely true, The Wayback Machine at the Internet Archive, continually scans the internet and saves old copies of information. RSS feeds have been adopted to allow subscribers to keep informed of changes made to the website.  And Wiki’s have sprung up in the attempt to allow content to be kept up to date and versioned.

What I would like to see is a standard for websites that allows the website itself to be versioned.  Make a website capable of being displayed as it was at a specific date and time.  Allow for milestones to be created for the content and the website as a whole.  Imagine having a draggable timeline above the website and being able to change the date you are viewing the website from.  This could even be extended to have a timeline per piece of content.

I am taking a lot of this idea from version control systems like CVS, SVN, or Git, but with one main difference.  Content should also be able to be predated to allow content to show up at future times as well.  Using version control as an embargo system is just one of the many advantages of thinking of a website as a viewpane on a timeline.

How long will it be until we create an internet of self archiving websites.  How long until we stop using technologies such as RSS and The Wayback Machine as stopgaps.  Let’s address this issue before it is too late, if it isn’t already.

SQL Server BULK INSERT Using a Data Field?

I have wondered for a while if there is a way to use SQL Server’s BULK INSERT command using BLOB or CLOB data Instead of a local file.

The reason for this is that when writing imports, using both Coldfusion and PHP, parsing and importing the data into the database is the weakest link.  It is relatively simple to write dynamic SQL to import data into my existing schema when copying from data already present in the database.  It is quite another matter to attempt to run thousands of INSERT statements from my web application.

I can’t ask a client to use SQL Management Studio to import their data into a table and then use a web app to run the import.  I don’t want to expose the database to the user and vice-versa.

At present I can only think of one good way to implement an import process and that is to allow the user to

  1. Upload the file.
  2. Create some sort of import plan (associate the content).
  3. Save that plan in some way.
  4. Run a scheduled task to run the import in batches.

I am dealing with imports of possibly hundreds of thousands of records.  Also note that I have limited access to the database as it is possible that the app will reside in a shared hosting environment.

Git for Windows Users

Here I am compiling information as a windows user that I needed or should have known while working with Git.

I still have issues trying to push using Git to a network server, as does a Mac using coworker.  I think there is some configuration issue or Git just doesn’t work well across networks.

MS SQL Server Time Dimension UDF

I use this function when writing reports.

Use:

SELECT
  time.Date
  , Count(tab.ID) AS [Count]
FROM
  dbo.TimeDimension('1/1/2007 00:00:00', '12/31/2007 23:59:59', 'month', 1) time
  LEFT OUTER JOIN
   TempTable tab
  ON tab.DateCreated BETWEEN time.Date AND time.DateEnd

Here is the function. I don’t know if there is a better way to do this, if there is can someone tell me. As far as I know I am the only person to post a function like this.

CREATE FUNCTION [dbo].[TimeDimension] (
 @DateStart datetime
 , @DateEnd datetime
 , @Type varchar(20)
 , @IncrementValue int
)
RETURNS @Dates TABLE ( Date datetime , DateEnd datetime )
AS
BEGIN
 DECLARE @DateCurrent datetime, @NextDate datetime
 SET @DateCurrent = @DateStart

 WHILE (@DateCurrent <= @DateEnd)
 BEGIN
 SET @NextDate = CASE (@Type)
 WHEN 'year' THEN DateAdd(year, @IncrementValue, @DateCurrent)
 WHEN 'quarter' THEN DateAdd(quarter, @IncrementValue, @DateCurrent)
 WHEN 'month' THEN DateAdd(month, @IncrementValue, @DateCurrent)
 WHEN 'dayofyear' THEN DateAdd(dayofyear, @IncrementValue, @DateCurrent)
 WHEN 'day' THEN DateAdd(day, @IncrementValue, @DateCurrent)
 WHEN 'week' THEN DateAdd(week, @IncrementValue, @DateCurrent)
 WHEN 'weekday' THEN DateAdd(weekday, @IncrementValue, @DateCurrent)
 WHEN 'hour' THEN DateAdd(hour, @IncrementValue, @DateCurrent)
 WHEN 'minute' THEN DateAdd(minute, @IncrementValue, @DateCurrent)
 WHEN 'second' THEN DateAdd(second, @IncrementValue, @DateCurrent)
 WHEN 'millisecond' THEN DateAdd(millisecond, @IncrementValue, @DateCurrent)
 END

 INSERT INTO @Dates ( Date , DateEnd )
 VALUES ( @DateCurrent , DateAdd(second, -1, @NextDate) )

 SET @DateCurrent = @NextDate
 END
 RETURN
END