Monday, 9 November 2009

Little cfquery gotcha

Here's something I do quite regularly:

<cfquery name="myquery" datasource="dsn">
INSERT INTO foo VALUES ('bar')
SELECT SCOPE_IDENTITY() as newId
</cfquery>

<cfset dosomethingwith = myquery.newId />
This is all good until you do something like:
<cfquery name="myquery" datasource="dsn">
INSERT INTO foo SELECT 'bar'
SELECT SCOPE_IDENTITY() as newId
</cfquery>

<cfset dosomethingwith = myquery.newId />
For whatever reason, CF craps out here and complains that 'myquery' is not defined. The problem only occurs, as far as I am aware, when you use SELECT syntax in your INSERT statement, something that is often neccessary. The workaround is straightforward, thankfully:

<cfquery name="myquery" datasource="dsn">
DECLARE @newId int

INSERT INTO foo SELECT 'bar'

SET @newId = SCOPE_IDENTITY()
SELECT @newId as newId
</cfquery>

<cfset dosomethingwith = myquery.newId />
Thanks to Neil Smith for the work around; I'd been using a separate query with @@identity for some time until today - far from good.

Dom

Sunday, 8 November 2009

Multiple Railo sites on single Tomcat host behind Apache

This is a follow on from Dave Shuck's excellent guide on setting up Railo on Tomcat behind Apache. A question was asked, and I paraphrase, 'How do you setup a single Railo instance that serves more than one Apache virtual host'. Well, here's how... almost...

Firstly, do not use mod_jk. Instead, enable mod_proxy, mod_proxy_ajp13 and mod_rewrite to pass on Apache 2 requests to Tomcat. This has benefits:

  1. Allows you to use Apache to control resources that would otherwise be under the control of Tomcat (i.e. you can use Apache's mod_rewrite on a .cfm resource where previously you would have to use Tomcat's rewriter). I find this preferable; I can use the plethora of Apache modules for cfm requests and leave Tomcat solely to dealing with the Java app side of things.
  2. Allows you to easily setup a single Tomcat host for multiple sites.

How to use mod_proxy_ajp13 with mod_rewrite


To use mod_proxy_ajp13, one simply adds rewrite rules to an Apache virtual host (e.g. in its .htaccess file). Here is a simple example:
RewriteEngine on

RewriteRule ^(.*?)/(.*?)\.cfm$ ajp://localhost:8009/mysite/$1/$2.cfm [P]
RewriteRule ^(.*?)\.cfm$ ajp://localhost:8009/mysite/$1.cfm [P]


My mod_rewrite skills aren't particularly hot, and I imagine you could put that in one rule, but hopefully that paints the picture. Simply put, we take all .cfm files and rewrite them to our ajp proxy.

How does that help?

Because we are proxying the request to Tomcat we can use any domain we like; in the case above I was using localhost but the apache virtual host could be for mysite.com. Let's say we have another Apache virtual host for myubersite.com, and setup rewrite rules like:
RewriteEngine on

RewriteRule ^(.*?)/(.*?)\.cfm$ ajp://localhost:8009/myubersite/$1/$2.cfm [P]
RewriteRule ^(.*?)\.cfm$ ajp://localhost:8009/myubersite/$1.cfm [P]


Now we have two Apache virtual hosts proxying .cfm requests to Tomcat on localhost. Here's how we could setup the localhost in Tomcat's /conf/server.xml to cater for the two sites:
<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context path="mysite/" docBase="mysite/" reloadable="true" privileged="true" antiResourceLocking="false" anitJARLocking="false"/>
<Context path="myubersite/" docBase="myubersite/" reloadable="true" privileged="true" antiResourceLocking="false" anitJARLocking="false"/>
</Host>


I have just this minute set this up on my Ubuntu desktop and currently, unsurprisingly, each site is still using a single Railo instance (each has the full Railo WEB-INF directory in its root). There is, however, a single Tomcat host and this is allowing me to control my box's memory more easily as memory appears to be allocated per host (somebody correct me) - when each of my dozen or so sites was on their own Tomcat host, I was running out of memory fast.

I'll leave it for someone to bridge the gap and figure out how to have a single Railo server config that controls all the individual sites (that still have their own 'web' configs). I don't have a need for that so I'm not going to kill my Sunday...

Dom

Monday, 25 May 2009

next-generator, an Illudium PU-36 based app that works with Railo

One rainy day, I sat down to auto generate a bunch of CFCs using Brian Rinaldi's marvellous Illudium PU-36 Code Generator. The trouble was, I was using Railo, and the blessed thing didn't work first time. Having zero patience, I decided to rewrite the generator using HTML and js only, and adding functionality that I had always wanted to see.

download

How is it different from the original?

This code is at least 50% Illudium PU-36. However, I have:

  • extensively reorganised the model;
  • made the project xml schema less implicit;
  • added the ability to generate code for multiple tables at once;
  • added the ability to serve the code as a zip file;
  • added support for Railo 3.1;
  • removed the option for viewing the generated code in the page;
  • removed Flex from the equation; the application front end is html with a little javascript.

That's all for now! Dominic

Wednesday, 25 March 2009

A little Railo Difference, Arguments scope

Here's a little something I found in Railo that differs from CF and which is seemingly undocumented.

I had need to create a function with no defined arguments. This function called another function, passing whatever arguments it was given to this second function. Before that happened, it checked whether a single, unnamed argument was being passed. If that was the case, it would give the argument an appropriate name and carry on. The code I had to check for this unnamed argument was:

if(StructCount(arguments) EQ 1 and StructKeyExists(arguments, '1')){
//...
}


This works in CF. In Railo however, if there is a single argument, the condition will always return true whether or not the argument is unnamed. This is because you can refer to arguments in Railo as either arguments[positionInArgArray] or arguments[nameOfArgument] (actually I'm presuming this here so do correct me if I'm wrong). If there is at least one argument, StructKeyExists(arguments, '1') always evaluates true in Railo.

Edit: Blair McKenzie just pointed out that the arguments scope can be treated as an array in ColdFusion (as well as Railo presumably). The only difference therefore, is that StructKeyExists(arguments, '1') returns true in Railo when using named arguments (with a name other than '1' indeed), it will return false in ColdFusion.

After a little headscratching I came out with the following solution, which works for both CF and Railo:

if( StructCount(arguments) EQ 1 and StructKeyList(arguments) EQ '1' ){
//...
}


This discovery came on top of issues converting a MS SQL Server Db to MySql, Windows to Linux and IIS to Tomcat (no apache). A bit of an ambitious move perhaps, but a good learning curve :)

Saturday, 26 April 2008

ColdFusion Encapsulation Gotcha

Good object design dictates that we encapsulate our objects, hiding direct access to object properties from outside code. Access to the values of these properties is often granted to outside code with the use of 'getter' methods.

The following, useless, component appears to encapsulate its 'foo' property using a getter method but, as we shall see shortly, does nothing of the kind:

<cfcomponent output="false" displayname="foobar">
<cfset variables.foo = StructNew()>
<cfset variables.foo.bar = "Hello world">

<cffunction name="GetFoo">
<cfreturn variables.foo>
</cffunction>
</cfcomponent>

Why is that not encapsulated?

The reason the 'foo' property is not encapsulated here is that ColdFusion passes certain variable types by reference rather than value. So when we return the variables.foo structure we are actually returning a reference to the original data in memory rather than the data itself.

The following code demonstrates what effect this has:

<h1>Encapsulation gotcha example</h1>
<cfset oFoo = CreateObject('component', 'foobar')><!--- the component defined above --->

<h2> Before:</h2>
<cfdump var="#oFoo.GetFoo()#">

<cfset fooReference = oFoo.GetFoo()>
<cfset fooReference.foo = "Wayne's world, excellent">

<h2> After:</h2>
<cfdump var="#oFoo.GetFoo()#">

If the 'foo' property were properly encapsulated here, both dumps would show the same thing. However, because we have a reference to the original data in the variables 'fooReference', we can make changes to the data directly (breaking encapsulation).

What to do about it?

It is important to note here that passing variables by reference saves memory - it is certainly NOT a bad thing! However, if encapsulation is more important to you, you can use the Duplicate() method to return a reference to a copy of the data which has the effect of returning the data itself:

<cffunction name="GetFoo">
<cfreturn Duplicate(variables.foo)>
</cffunction>

Final note

ColdFusion passes queries, structures and external objects such as COM objects and CFC instances by reference.

Strings (including numeric values) and arrays are passed by value and do not need to be 'duplicated' in this way.

Here is a link to an Adobe livedocs page that talks about passing variables to and from functions in detail:

http://livedocs.adobe.com/coldfusion/7/htmldocs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=ColdFusion_Documentation&file=00001008.htm

Sunday, 20 April 2008

Scatting with ColdSpring

I really like ColdSpring - quiet, clean and powerful - mmmm (forgive me, I'm very tired). There is one thing that I have found that bugs me a little however; the verbosity of defining aspects and advisors.

Here's a quick xml sample of creating a really simple aspect and applying its advice to a bean:


<beans>
<!-- state checker advice and advisor -->
<bean id="stateChecker" class="aopxml.stateChecker" />
<bean id="stateCheckerAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">
<property name="advice">
<ref bean="stateChecker" />
</property>
<property name="mappedNames">
<value>*</value>
</property>
</bean>

<!-- test component with proxy -->
<bean id="testerTarget" class="aopxml.tester" singleton="false" />
<bean id="tester" class="coldspring.aop.framework.ProxyFactoryBean" singleton="false">
<property name="target">
<ref bean="testerTarget" />
</property>
<property name="interceptorNames">
<list>
<value>stateCheckerAdvisor</value>
</list>
</property>
</bean>

</beans>

This is example is from my blogpost http://fusion.dominicwatson.co.uk/2008/03/stricter-oop-using-aop.html.

Worse still, if I want to apply my aspect to any another beans, I would have to explicitly do so by defining a proxy for each bean.

So what's the solution?

The first thing I thought was to have specific AOP xml tags for the configuration that would allow you to define aspects and instruct ColdSpring to automagically create proxies for you based on the component name rules you supply it.

I posted this thought on the ColdSpring google group and the reply made me look to the Spring framework (on which ColdSpring is based) - what does the Spring framework do? Well, it does pretty much exactly as I suggested:

http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-schema

So, with a minor adaption for ColdFusion (though not budging from the Spring Xml schema), here is how the above Xml example could look:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop">
<!-- 'new' aop tags -->
<aop:config>
<aop:aspect id="stateCheckerAspect" ref="stateChecker">
<aop:around pointcut="*.*" method="invokeMethod"/>
</aop:aspect>
</aop:config>

<!-- 'aspect' beans -->
<bean id="stateChecker" class="temp.stateChecker" />

<!-- 'regular' beans -->
<bean id="tester" class="temp.tester"/>
</beans>

The above XML defines an Around advice that will be applied to every bean and every method in the factory. Of course, different rules could be setup and I think the benefit is quite graphical.

This got me all excited and sent me on an all night coding spree. The result was a new ColdSpring bean factory that would take the Xml above and make it work. Its just a proof of concept and a little rough around the edges but it shows what can be done with reasonable ease (thanks to the excellent codebase already in ColdSpring).

The extended factory will indeed parse most of the aop elements defined in the Spring schema. I won't go into detail as they are very well documented in the Spring documentation that I linked to. However, here is a quick example of an aop:config that the extended factory will do stuff with:

<aop:config>
<aop:pointcut id="aopxmlPackagePC" expression="aopxml.*.Add*"/>
<aop:aspect id="stateCheckerAspect" ref="stateChecker">
<aop:around pointcut-ref="aopxmlPackagePC" method="invokeMethod"/>
</aop:aspect>
<aop:aspect id="someErrorCatchingAspect" ref="someAdviceBean">
<aop:pointcut id="thisAppServices" expression="com.myCo.thisApp.services.*.*"/>
<aop:after-throwing pointcut-ref="thisAppServices" method="afterThrowing"/>
</aop:aspect>
</aop:config>

You can download the simple working example here. You may need to create a mapping to whereever you unzip it (mapping called 'aopxml').

A disclaimer: this is completely unofficial and just a proof of concept - I'm just scatting. Enjoy :)

Saturday, 5 April 2008

Stricter OOP without AOP! Sort of ;)

I've been playing around with the idea of forcing my components not to add or remove variables from their 'variables' scope, other than when instantiated. Its something I'd like not to be possible and I'd like a ColdFusion error if it happens. I blogged my first effort at cracking it here:

Stricter OOP using AOP!

The biggest downside to this was complexity of implementation. While I don't mind hidden complexity, using AOP meant that I would have to explicitly declare that each of my objects was wanting to use this feature/'aspect' - the effort in doing so using ColdSpring far outweighed any benefit. This was a 'global aspect' that would be best placed in a global base class if possible.

So, how to wrap all of a component's methods automatically using a base class that it extended? The concept is similar to AOP but it would lack the hassle of having to apply AOP to my model. Of course, the hassle would be figuring out how to do it!

A very long and steep-learning-curved night later and I have a working version. It borrows from the concept used in ColdSpring's AOP implementation of creating a temporary file in order to create component methods on the fly (mixins). The use is slightly different however. The following is an attempt to explain the base class constructor as concicely as possible:

  1. Store copy of self in a state variable.

  2. Create temporary cfc file with methods of the same name as those in this component. The body of these methods have a single line that calls a 'CallMethod()' method, passing the method name and any args as arguments.

  3. Instantiate temporary cfc and delete the file.

  4. Overwrite the original component methods with those in the temporary component

  5. Removed methods used in this process from the component

The result is a component that appears unchanged (from the outside) but that has each of its methods replaced with a wrapper that invokes the samed named method on a copy of the original component.

Once this component has been written, implementation couldn't be much easier. Simply extend the component and call it's constructor from within the extended component and you're done.

Rather than have all that code be used specifically for monitoring a component's variables, I first created an uber-base class which for now I have called selfproxy. This does what I have described above but does nothing useful in the 'self proxied' methods. To do something useful (such as monitor the variables scope), I just extend the component and override its method interceptor.

This 'self proxying' mullarky lacks the precision and flexibility of AOP, but if you're painting with a broad brush it might be a useful thing.

A working example (tested on ColdFusion 8 running on Windows XP).

I'm just scatting on a theme here and would be interested to hear any constructive criticism ;)

Anyways, time for bed!