Thursday, May 23, 2002

kwfu: ('cfmx','pagecontext','jsp')
I think there are so many features like this in CFMX that there's going to
be a whole lot of re-learning and re-evaluating of what up to now have been
considered standard practices in CF, and probably more importantly things
which up to now have been considered more or less taboo.

I have some personal favourites from the 'Things that have changed'
department:
cfimport - allows you to have dynamic custom tag paths.
cftrace - Cuts out 90% of the cases where I'd be using cfdump/cfabort to
debug.
cflogin - allows multiple authentication mechanisms to fire the login code -
This could turn out to be a two edged sword, but there you go.

There are of course a whole bunch of new features like native XML support,
Flash remoting, CFCs etc.

As someone famous once said 'We live in interesting times'.

Originally posted on a closed mailing list. - Thanks Robi

UPDATE: Ray Camden pointed out that the multiple authentication mechanism is a feature you don't have to use.

Ray: you should note that this 'feature' of cflogin is
something you do not have to use. If you do not use the cflogin scope,
then you can restrict logins to just one source (form, url, whatever).
In other words, do not do this:

<cflogin>
<cfif isDefined("cflogin.name") ....

Use this:

<cflogin>
<cfif isDefined("form.name") ....


Spike: I guess I wasn't clear enough in what I was saying. Of course you could write code to handle this manually, but it's kinda nice to have the ability to accept logins from flash remoting and from form scope without so much as a cfif. This, of course opens up a whole bunch of problems like script kiddies who use dictionary files to attack sites secured with http basic authentication. That's where I see the 2 edged sword thing. In practice I would probably handle things manually for this very reason, but that may not be applicable in every situation.
kwfu: ('cfmx','class files','compile')
This code will batch pre-compile a complete directory tree of CFMX templates. The original code is credited to an un-named Macromedia employee. He is only un-named because I haven't got round to checking with him if I can publish his name.

In ColdFusion MX:

Stick this in a batch file, save as compiler.bat, and pass it a directory to compile:

@setlocal
set NEO_INSTALL=c:\cfusionmx
set PATH=%NEO_INSTALL%\runtime\bin;%PATH%
java -classpath %NEO_INSTALL%\lib\cfusion.jar
coldfusion.tools.Compiler -webroot %NEO_INSTALL%\wwwroot %*
@endlocal


called like so:

compiler.bat c:\cfusionmx\wwwroot\myapp

Compiles all files below that directory.

Spike
kwfu: ('cflock','cfmx')

The following code is credited to an un-named employee at Macromedia. The only reason he is un-named is that I haven't go round to getting his permission to use his name here. Suffice it to say that he is one of the core team of engineers who put together the ColdFusion MX engine. What he has to say is probably well worth listening to.

<!---
This code will not make Neo explode or turn into a frog
or anything -- to my mind that is *bad.* A core dump
is a better thing than silently corrupted data.
--->

<!--- no CFLOCK --->
<cfset session.cartTotal = session.cartTotal + currentPrice>
<!---
There really is enough time between the right-hand side
read of session.cartTotal and the left-hand-side write
for another request to get in before us and modify
session.cartTotal; our CFSET will step on that other
request's data. That is bad.
--->

Make your own mind up if you still want to use cflock.

Spike
kwfu: ('cf','cflock','full checking')

In some versions of ColdFusion Server, there is an option in the ColdFusion Administrator related to the locking of shared memory variables. One of the options allows you to tell the ColdFusion Server to check all the code it processes to ensure that shared memory variables do not suffer from memory corruption. The option in the CF Administrator is referred to as 'full checking' in the following ramblings.

beware of trusting the results of turning on full checking...

If you do this:

<cflock scope="session" type="readonly" timeout="2">
<cfset userprofile = session.useprofile>
</cflock>

Then later in your code you do this:

<cfset userprofile.emailaddress = 'bob@somedomain.com'>

You are actually modifying the data in the session scope, but the full
checking will not pick it up.

In order to stop this being a problem you could do 1 of 2 things:

Option 1:
<cflock scope="session" type="readonly" timeout="2">
<cfset userprofile = duplicate(session.useprofile)>
</cflock>

This will create a completely separate copy of the userprofile. Depending on
what you are doing you might want this.

Option 2:
<cflock scope="session" type="exclusive" timeout="2">
<cfset userprofile.emailaddress = 'bob@somedomain.com'>
</cflock>

This will safely update the data in the session scope. Again, depending on
your circumstances this may be what you want to do.

Good luck hunting down blocks of code that need to be locked as in option 2.

Spike

Originally posted in response to a thread on the UK ColdFusion User Group mailing list: dev@lists.cfdeveloper.co.uk.
kwfu: ('cf','application','cflock')

Some may find the following mutterings on the ColdFusion application and locking framework useful.

A variable which is created in application.cfm like so:

<cfset myvar = "Foo">

Does not get created in the application scope. It gets created in the
variables scope.

Since application.cfm gets auto-included at the start of every page request
this variable becomes available, as myvar, or variables.myvar, to the
template which was requested on the url, and any other templates which are
called by cfinclude. The variable will not be available to any templates
which are called as custom tags unless you explicitly pass it in there as an
attribute.

If you want the variable to be available to all templates you must
explicitly put it into the application scope like so:

<cfset application.myvar = "Foo">

This will be available to all templates as application.myvar, but not as
myvar, or variables.myvar.

In order to maintain data integrity, and for stability you must wrap reads
and writes to the application scope in a cflock:

Setting:
<cflock scope="application" type="exclusive" timeout="1">
<cfset application.myvar = "Foo">
</cflock>

Reading:
<cflock scope="application" type="readonly" timeout="1">
<cfoutput>#application.myvar#</cfoutput>
</cflock>

In CF 4.5, the Request scope was added so that the gazillions of custom tags
that Spectra uses could all access data safely without having to put cflocks
everywhere, or passing all the data around as attributes to the tags.

The request scope is also available to all pages which get executed for a
single request, so you could quite safely do this:

In application.cfm:
<cfset request.myvar = "Foo">

In some custom tag:
<cfoutput>#request.myvar#</cfoutput>

Woo Hoo!!!

No locking required...

BUT...

Since there is a new request scope for every user, you will be having a
separate copy of the data in that scope for each concurrent request. The
default maximum for concurrent requests is 6, so you will probably be having
up to 6 times the amount of data in the request scope in memory on a busy
server. If you have a lot of data in there, this can become siginificant, so
it's something to watch out for.

Apart from that, it's up to you what you'd prefer. Request or application
scopes are available to all files which get processed in a request, but you
can't read variables from them unless you specify the scope name explicitly.
This is probably a good idea anyhow, but most people, myself included, are
just too lazy to do it for all variables.

Spike

Originally posted in response to a thread on UK ColdFusion User Group mailing list: dev@lists.cfdeveloper.co.uk.