The amazing adventures of Doug Hughes

Archive for April, 2008

This is just a quick blog post and not technical at all, as yet. I am curious to know how many out there are using ColdSpring+ModelGlue+Transfer in Production, on a live web site. Also, if any of you have done any reasonable load-testing of applications using ColdSpring+ModelGlue+Transfer. It would also help if you could state what version of ColdFusion-JVM you are running this on. Thanks in advance to all who reply.

Deploying apps can be a pain. Its not so much the copying of files from one place to another, but all the related tasks you have to remember to do!

As an example, we tend to have local development, staging, and production servers. Each of these servers tend have different configuration settings. On staging I might have a datasource called myAppDev. In staging it might be known as myAppStaging and in production it could be known as something completely different.

Then there are the issues of mappings, custom tag paths, event gateways, email servers, reloading applications, clearing template caches, etc, etc. Historically, Ive avoided using a number of advanced features of ColdFusion because of the configuration required on the server and the requirement that I remember tasks that need doing on each deployment.

Ill wager that the vast majority of websites and applications are quite simple and can easily be deployed via a copy and paste process or FTP. However, the larger and more complex an application and hosting environment become, the more arduous this process gets. At this point you begin to lust for automation but there are some things that are just hard to automate. In these cases you need to automate as much as you can and have a script for any other steps you need to take manually.

Well, at Alagad, weve been pretty stuck at the last mile. For some of our apps we have an ANT build script which essentially calls a remote cfm file that runs another ANT file. This remote ANT file would export the application out of Subversion and to the correct location depending on if were deploying to staging or production. Finally, it might make some configuration changes to the application such as setting Model-Glue and Reactor to production modes.

However, many of our applications run in production with the trusted cache enabled. Some of our applications require mappings or event gateways. Even if we manually set some of these up in the ColdFusion server, we still have to remember all this stuff when if we ever move to a new server or if we cluster our applications. Beyond that, there are still some things you have to do manually on each deploy such as clearing the template cache.

This problem started me thinking about the ColdFusion Admin API. As of version 7, ColdFusion shipped with a collection of CFCs which provided complete access to all the capabilities of the ColdFusion Administration interface. Why couldnt we create a set of reusable scripts which would use the Admin API to do things we would have to manually do while deploying an application? This weekend I decided to give it at shot and the result is a new Alagad offering known as CFANT.

CFANT provides a default mechanism for deploying applications remotely and also includes ANT tasks for everything you can do via the Admin API.

Deploying Applications Remotely

The CFANT project should be installed under your applications webroot in a directory named cfant. This directory should be web accessible. If youre squeamish about this cfant has some properties you can tweak to change the the directorys name and location and you can always make your build.xml file not web-accessible.

Under this folder there is a build.xml file. This file is heavily laden with comments to help you out, but the file itself is really just a starting point. If you look at the file youll see that the default comes with three targets: BuildLocal, BuildStaging and BuildProduction.

Lets start by looking at the BuildLocal target is what you would run locally to kick off the remote build processes. BuildLocal is also the default target. The BuildLocal target defines a few inputs. You can specify whatever inputs your script requires, but I recommend keeping the TARGET input at least as this specifies the name of the remote target youre executing. The rest of of the inputs would be inputs required for the remote target to run. Due to ColdFusions case insensitivity, I recommend you uppercase any values that will be passed to a remote script.

All of the inputs and any properties you may specify need to be passed to the remote build runner. The remote build runner is a simple CFM file in the /cfant/build directory that is executed via HTTP by the local build target. The remote build runner runs ANT on the remote system, specifies the same build.xml file that youve been editing, and runs the task specified. Any arguments that come in through the url as passed as arguments into ANT.

Two things are implicit in this process:

First, you must have ANT installed on your server and it must be accessible via the path. Or, in other words, you must be able to run ANT from the command line without specifying the full path to the ANT executable.

Secondly, you must have already manually pushed CFANT to your remote server. The remote build runner wont run if it and the build XML and various other files it depends on are not there.

At this point your remote build script runs and does whatever you told it too. For a typical Alagad build script, wed probably export code from Subversion, change some XML configuration, and reload the application via a URL.

But, I still need to use some of the features of the ColdFusion Admin API which is why I also included…

ColdFusion Administrator ANT Tasks

CFANT includes 320 ColdFusion administration ANT tasks. Each of these tasks map to a function on the ColdFusion Administration API. Each of these tasks are provided as a class under the bin/com/alagad/cfant folder and must be loaded using the <taskdef> ant tag.

To use any of these tasks youll first need to use the ANT task. (No, this is not the same things as the coldfusion tag. The name is confusing, I know. There may be others that are similarly confusing.) Heres some sample XML:

Note that I use taskdef to load the cflogin task and then use the cflogin task. At this point I can use any of the other tasks.

Unfortunately, cfant doesnt come with any real documentation. Instead, youll want to use the documentation for the Admin API. And, also unfortunately, that documentation is next to non-existent.

To work around this, I recommend browsing directly to an Admin API CFC specified in the documentation. For example, go to http://yoursite.com/CFIDE/adminapi/administrator.cfc. ColdFusion will prompt you for your administrator password and show you automatically generated documentation.

Any public method on any of the Admin API CFCs has a corresponding tag. For example, the login method on the administrator.cfc has the cflogin task.

Each of the arguments on the Admin API method has a corresponding attribute on the task. For example, the login method accepts four arguments: adminPassword (required), adminUserId (optional), salt (dont use), rdsPasswordAllowed (optional). The task has corresponding attributes which you use in the exact same manner. Youll see in the example above that the cflogin task was provided the one required argument of adminPassword.

If an admin function returns a value you can use a property attribute to specify an ANT property to place the results into. Heres an example using the cfverifyDsn task:

Again, the taskdef tag loads the cfverifyDsn task which maps to the verifyDsn function in the admin API. This method accepts an argument named dsn which is the name of the datasource were verifying. The method returns a boolean value and you can use the property attribute on the CFANT task to specify a property name. In the example above we then output the results of this using the ANT echo task.

Any function which returns a value (and the ColdFusion team has property indicated in their ColdFusion code returns a value) will have a property attribute. If the function returns a complex value this is dumped to text and the dump is returned.

How do the CFANT tasks work?

I’m glad you asked! Essentially, I wrote a generator.cfm which gets the metadata for each of the Admin API CFCs. Based on that, I generated a set of remote proxy CFCs that make the public methods on the Admin API remotely accessible. I then generated a simple Java class for each of the methods on the Admin API CFCs. This class ultimately extends the ANT task object and calls remote methods on the remote proxies. Returned values are parsed for errors.

Overall, because this is generated code and a new project, the vast majority of CFANT is completely untested. If you find a problem or have a suggestion please register with the projects Trac site and file a ticket. The Trac site is located here: http://trac.alagad.com/cfAnt.

I came back from lunch today to find a pleasant surprise sitting in my IM client. Dan Wilson, programmer and CFUG manager extraordinaire, had sent me URLs for the Triangle Area ColdFusion User Group’s calendar of events!

Just a week ago I had been bemoaning the fact with Dan that I never know when things are going on. I don’t make a habit of going to the user group’s website and I had avoided signing up for the mailing list so I pretty much was out of the loop.

This calendar should give me fewer reasons not to show up to these events. Other user group managers should make a note of this. All Dan did was create a new calendar in Google Calendar and make it public. All I did was add it to my Google Calendar.

Also, Dan Wilson and Jim Priest had a the great idea of organizing a cflunch! What is that, you may ask? Well, it’s an informal gathering where user group members can congregate and have an unstructured lunch. Why are we always so focused on presentations when something informal like this can sometimes be just as valuable?

As for me, I’ll be there! (Especially with the new calendar to help me.)

This is a quick blog entry to call out to the Flex and ColdFusion community. If youre looking for contract work, we have some that you might be interested in.

Firstly, we have a ColdFusion project were working to secure which we need to staff with a full time programmer with Model-Glue and ColdSpring expertise though the end of December.

Secondly, we have a Flex project were working to secure which would be going live on August 1st. This project is a refactoring of an existing application into a Flex framework such as Cairngorm or EasyMVC and then building new features on top of the application. The backend for this project is ColdFusion.

Here at Alagad, we typically use an “interface driven architecture” process when building applications. In other words, we start with the user interface of the application and get it completely finished before developing any of the backend architecture and databases. This allows us to easily make changes when the client sees something they don’t like without having to make changes to the object model, service layer, database structure, etc.

However, we are currently working on a project which has very little existing design to work from and one of the biggest goals of the project is to increase end user usability. So, I am proposing to the client that we enlist the services of a professional interface architect – somebody whose focus is application usability and design, not necessarily programming. The problem is, we don’t have anybody on staff that has this skill set to the level needed. This is where we need your help. Are you an interface architect or do you know anybody that you could refer? If so, please drop me a line at jchastain at alagad dot com.

I am slowly publishing a series of blog posts relating to clustering in particular with ColdFusion and JRun. It can get fairly complicated pretty fast and I urge all who are going to embark on clustering to plan out how you want to cluster and why. Another key issue is to make sure when we are creating a web application that it designed and engineered from day one with clustering in mind. I have helped so many clients who hit major problems when they start building clusters, largely because the application was too tightly coupled to the environment it is running in. Hard-coded directory paths would be a classic example.

In this blog posting I wanted to illustrate an interesting concept, well two in reality, Horizontal Clustering and Vertical Clustering. This was prompted by a comment from someone on another blog piece I did on clustering, here. In this first graphic we have Vertical Clustering…

In this case we are running “RoundRobin” with “Sticky Sessions”. What this does is cause the Hardware Clustering Device to send User 1 to the first web-application server and they stay there for the duration of their session, unless that web-application server fails. User 2 is sent to the second web-application server and they stay there for the duration of their session, unless that web-application server fails. At the software level, via CF-JRun exactly the same procedure is taking place.

Next we have an example of Horizontal Clustering…

In this case we are running “RoundRobin” with “Sticky Sessions”. What this does is cause the Hardware Clustering Device to send User 1 to the first web-application server and they stay there for the duration of their session, unless that web-application server fails. User 2 is sent to the second web-application server and they stay there for the duration of their session, unless that web-application server fails.

At the software level, via CF-JRun we have two clusters which actually span the two web-application servers in some ways usurping what the Hardware Clustering Device is doing. User 3, for instance, can actually be served by the second Web Application Server if “RoundRobin” is enabled at the Software Clustering level. In this sort of set-up, we have the Hardware Clustering Device performing more of a fail-over role whilst the Software Clustering is slanted more toward load-balancing.

In both cases it would be good to have Session Replication enabled and in the case of Horizontal Clustering it is essential or Client Variables could be used but of course complex objects cannot be stored as Client Variables. I hope to cover this concept in greater detail as I go through the series in HA and clustering with ColdFusion-JRun. As I stated at the beginning of this piece, careful planning with an eye to the future is essential when building any sort of cluster.

There have been several blog posts recently about class-loading issues apparently linked the use of the Sun-Java 1.6 (6.0) JVM. Mark Mandel has a detailed article on this here.

Before seeing this article we had been working on optimizing a ColdSpring-ModelGlue-Reactor application. We blogged our progress in this article. We thought a reality check was a good idea and ran some load tests comparing this same application performance in Java 1.5 and 1.6. Once again we observed better performance in 1.6; here are the results. These results are for a 50 Virtual User (vUser) Test for 1 hour with 8 second think time (delay between clicks) comparing Java 1 5 to 1.6.

Firstly Java 1.5

Total Number of Clicks: 13,345 (0 Errors)
Average Click Time of all URLs: 5,298 ms

Secondly Java 1.6

Total Number of Clicks: 15,563 (0 Errors)
Average Click Time of all URLs: 3,348 ms

As we observed before, Java 1.6 performs better in load tests than Java 1.5 and this includes instantiation time. Here are two graphs which show the same behavior…

Java 1.5

Java 1.6

In these two 3D graphs, the more users that are the left axis of the graph, the better. In the 1.5 version, most users are in the middle right part of the graph, whilst in the 1.6 version there are more users in the left part.

One thing we are saying here is to load-test all applications before deployment, ideally across different environments and particularly before down grading to an earlier version of anything. In addition, consider the base architecture of all applications, at the end of all that we do, user experience is paramount, users have no interest or concern as to what coding paradigms we use.