Archive for the ‘Tech Stack’ Category

Performance of CFScript

September 9, 2011

I have been developing ColdFusion on and off for about 10 years, and one topic that has been controversial the entire time is CFScript. The arguments go back and forth: ‘It’s too slow’, ‘it’s not ColdFusion’, ‘It looks like Javascript, but isn’t’.

On our team, the majority of our code is written in plain CFML. With new team members coming onboard with stronger backgrounds in Java-like languages, more and more CFScript is starting to show up, especially in the business-tier. The question of performance has come up, and though we do not have real numbers to back it up, the general consensus is that the performance difference is negligible, and each team can choose if they want to use CFML or CFScript going forward.

Not satisfied with a general feeling, I set out to conduct a very simple test, and see what ColdFusion does behind the scenes when compiling a simple component in CFML, and the same component written in CFScript. The component I came up with has a single function, with a single numeric argument. It then loops a variable number of times, constructs a struct, and does some simple math.

First, the CFML version. I added a suppressWhitespace=”true” directive around the component, in addition to output=”false”, to be completely sure that whitespace would not be emitted.

<cfcomponent output="false">
<cfprocessingdirective suppressWhitespace="true">
	<cffunction access="public" name="doStuff" returntype="void"  output="false">
		<cfargument name="iterations" type="numeric" required="true" />
		<cfloop from="1" to="#arguments.iterations#" index="local.i">
			<cfset local.myStruct = {a=1,b=local.i}/>
			<cfset local.myStruct.c = local.myStruct.a*local.myStruct.b/>
		</cfloop>
	</cffunction>
</cfprocessingdirective>
</cfcomponent>

Next up, CFScript. Notice there is no output=’false’ or suppressWhitespace equivalent. As I will show in a moment, CFScript components do not emit whitespace.

component {
	public void function doStuff(required numeric iterations){
		for (local.i = 1; local.i <= arguments.iterations; local.i++) {
			local.myStruct = {a=1,b=local.i};
			local.myStruct.c = local.myStruct.a*local.myStruct.b;
		}
	}
}

I turned on ‘Component cache’ and ‘Save class files’ in the ColdFusion Administrator, and ran the resulting .class files through the JAD decompiler.

The results of the decompilation don’t look the greatest here on WordPress, so here are links to the resulting decompiled Java classes:

A few observations:

  • The CFML version produces a runPage() method that has a lot of logic dealing with the cfprocessingdirective tag
  • Even with output=false and suppresswhitespace, the CFML version has several calls of the format _whitespace(out, “\r\n\t\t\t”);. With the suppresswhitespace in place, this still results in several function calls in the ColdFusion runtime, going from CfJspPage, to NeoPageContext, to CFOutput, before finally deciding to throw it away.
  • CFScript has no such whitespace method calls, so adding output=’false’ to CFScript is not necessary.
  • The CFML and CFScript versions of the FOR loop compile quite differently. The CFML version is somewhat tame at ‘for (; CfJspPage._checkCondition(t11, t15, t13); CfJspPage.checkRequestTimeout(“CFLOOP”))’, while the CFSCRIPT version is a little more complex, doing bit shifting in one place and a few extra casts.

Other than these differences, the compiled code is almost identical.

I also used JMeter to run simulated usage across the two components. With 8 simulated users across 4000 calls, each calling both CFCs in a random order and each passing 10,000 to the component (resulting in 40m total iterations), both averaged around 116ms per call, and consistently came within 3-4ms of each other.

This is far from an exhaustive comparison of CFML and CFScript. There are things that CFML can do that either you cannot do at all in CFScript, or have to jump through some hoops to do. Both flavors of the language have their places, and as for business-layer code that can be written without jumping through hoops, CFScript performs just as well as CFML.

Logging in to Salesforce from ColdFusion

August 31, 2011

We have been working the last few months on an experiment with Salesforce.com. The code is some of our first to be written almost purely using CFScript and Hibernate. One of our challenges was communicating with Salesforce, in particular, their fairly new REST API. Their API documentation is pretty good, but the one area that was somewhat lacking at the time was how to log in. Once we figured it out, the solution was rather simple, it just took a little while to find the right combination of parameters.

We hope to eventually release our entire CFC for talking with Salesforce, which has a lot of convenience methods to get, set, upsert, and describe Salesforce objects, but for now, here is our code to log in and get an object.

public boolean function logIn() {
	if (variables.token EQ '' OR arguments.force) {
		local.http = new Http(url=variables.salesforceInstance & '/services/oauth2/token',method='post');
		local.http.addParam(type='formField',name='grant_type',		value='password');
		local.http.addParam(type='formField',name='client_id',		value=variables.CLIENTID);
		local.http.addParam(type='formField',name='client_secret',	value=variables.CLIENTSECRET);
		local.http.addParam(type='formField',name='username',		value=variables.USERNAME);
		local.http.addParam(type='formField',name='password',		value=variables.PASSWORD);
		local.http.addParam(type='formField',name='format',		value='json');

		local.httpSendResult = local.http.send();
		local.httpResult = httpSendResult.getPrefix();

		if (StructKeyExists(local.httpResult, "responseHeader")
				&& StructKeyExists(local.httpResult.responseHeader, "status_code")
				&& local.httpResult.responseHeader.status_code EQ 200) {
			local.stringResult = gatherResponseString(local.httpResult);
			//variables.json is an in-house wrapper around 'org.json.simple.JSONValue'. DeserializeJSON may work for you as well
			local.json = variables.json.toObject(local.stringResult);
			variables.token = local.json.access_token;
		} else {
			variables.token = '';
			local.errorString = gatherResponseString(local.httpResult);
			if (StructKeyExists(local.httpResult, "ErrorDetail")) {
				local.errorString &= ", detail: " & local.httpResult.ErrorDetail;
			}
			throw (message='Unable to authenticate to SalesForce: ' & local.errorString, type='lampo.salesforce.loginerror');
		}
	}
}
public any function getObject(required string sfid, required string type, array fields) {
	local.url=variables.salesforceInstance & '/services/data/v' & variables.apiVersion &'/sobjects/'&arguments.type&'/' & arguments.sfid;

	if (NOT isNull(fields) AND ArrayLen(fields) GT 0) {
		local.url = local.url & '?fields=' & ArrayToList(fields);
	}

	return makeJsonGetCall(url=local.url,errorMessage='Unable to find ' & arguments.type & ' with sfid ' & arguments.sfid);
}

/*************** HELPER FUNCTIONS ********************/
private function gatherResponseString(required any httpresult) {
	if (IsBinary(httpResult.FileContent)) {
		return CharsetEncode(httpResult.FileContent, httpResult.CharSet);
	} else {
		return trim(httpResult.FileContent);
	}
}

private any function makeJsonGetCall(required string url, required string errorMessage) {
	local.httpResult = makeCall(arguments.url,'GET',{});

	if (local.httpResult.responseHeader.status_code EQ 200) {
		local.fromJson = variables.json.toObject(gatherResponseString(local.httpResult));
		return local.fromJson;
	} else {
		throw (message=arguments.errorMessage & ' (status: '& local.httpResult.responseHeader.status_code &')',type='lampo.salesforce.objectNotFound')	;
	}
}
private any function makeCall(required string url, required string method,required struct params) {
	local.http = new Http(url=arguments.url,method=arguments.method);
	for (paramType in params) {
		for (paramKey in params[paramType]) {
			if (paramType NEQ 'header' or paramType neq 'Authorization') {
				local.http.addParam(type=paramType,name=paramKey,value=params[paramType][paramKey]);
			}
		}
	}
	local.http.addParam(type='header',name='Authorization',value='OAuth ' & variables.token);
	local.httpSendResult = local.http.send().getPrefix();

	if (local.httpSendResult.responseHeader.status_code EQ 401) {
		throw (message = 'Unable to log into SalesForce: ' & local.httpSendResult.responseHeader.status_code & '('&gatherResponseString(local.httpSendResult)&')',detail=gatherResponseString(local.httpSendResult),type='lampo.salesforce.loginFailure');
	} else {
		return local.httpSendResult;
	}
}

Coldfusion 9 ORM, Caching and Autocommit

August 22, 2011

We have been using ColdFusion 9 for a few months now. With all new code that is developed, we have been abandoning <CFQUERY> in favor of CF9’s ORM, which is based on Hibernate. This is a great technology that lets us focus more on work that matters, instead of coding lots of repetitive SQL queries. But, as with any new technology, there are some gotchas that developers have to be aware of. Two such gotchas have come up recently on projects I have worked on, and I am going to share those with you today.

Setup

For this simple example, we are going to use a very basic table.

create table dbo.person (
	[id] [int] IDENTITY(1,1) NOT NULL,
	[first_name] [varchar](128) NOT NULL,
	[last_name] [varchar](128) NOT NULL,
);

In traditional ColdFusion, if you wanted to update a person, you would perform a with an update statement, like so:

update person set first_name=
where id =

In ColdFusion 9 with ORM, you have an object that represents a person, as defined in Person.cfc. Note that I will be using 100% CfScript for the rest of this article.

component persistent="true" table="person" {
	property name="id" fieldtype="id" generator="native";
	property name="firstName" column="first_name";
	property name="lastName" column="last_name";
}

To update the person, you would write something like the following:

local.person = EntityLoadByPk('Person',arguments.personId);
local.person.setFirstName(arguments.newFirstName);
EntitySave(local.person);

So far, this is all basic ColdFusion ORM. Let’s look at some things you need to be aware of as your application grows in complexity.

Gotcha 1 : Caching

Consider the following MxUnit code:

public void function testFunction1() {
	local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},true);
	local.person.setFirstName('Jane');
	otherFunction1();
}
private void function otherFunction1() {
	local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},false);
	assertEquals(1,local.person.size());
	assertEquals('Jane',local.person[1].getFirstName());
}

In function otherFunction1, we have asked Hibernate to give us John Doe a second time. One would expect this to return a fresh copy of John Doe, but actually it has returned a reference to the same person as inside testFunction1. The query is indeed performed on ‘John Doe’, but in the scope of the current request, that maps to an object already in memory, one that has a new first name. You can read a little more about this form of caching in the CF docs.

It is important to also see what happens when you use EntityReload. Since both variables point to the same instance from the cache, an EntityReload on will will reload the other. Consider the following:

public void function testFunction2() {
	local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},true);
	local.person.setFirstName('Jane');
	otherFunction2();
	assertEquals('John',local.person.getFirstName());
}
private void function otherFunction2() {
	local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},true);
	assertEquals('Jane',local.person.getFirstName());
	EntityReload(local.person);
	assertEquals('John',local.person.getFirstName());
}

Gotcha 2: Autocommit

By default, Hibernate is configured to commit any changed objects. In our above example, the EntitySave(local.person) is completely optional – at the end of the request, the changes to the person will be persisted to the database. What’s bad about this is that in the pre-ORM world, developers in ColdFusion are used to explicitly updating the database via____ or some other framework. You would think that the equivalent would be calling EntitySave.

This recently bit me when I was validating some data before writing it back to the database. We have a form that is used to update contact information, and allows for our users to add new types of contacts to a person (such as billing e-mail, toll-free number, etc). There are some rules involved, one being that certain people must have one and only one billing e-mail address. Instead of validating the form and the database separately, the code I was working on converted the new contact field from the form into a new database object (via EntityNew), added it to the list of existing contact fields, and then ran the validation on the objects. If validation failed, the idea was to present the user with an error so they could correct it, and new or updated information would not make it to the datbase. Instead, Hibernate went ahead and saved all changes to the database, and allowed the error message to be displayed.

To work around this, there are a few things you can do:

  1. Don’t mess with objects unless you want your changes to always be committed
  2. Turn off autocommit by adding <property name=”connection.autocommit”>true</property> to your hibernate.xml file.
  3. If you want to back out any changes you have made to an object, call EntityReload(local.myEntity) to discard changes
  4. Use transactions
I will elaborate a little bit on #4. Assume the database has John Doe in it as you look at the following MxUnit code:
public void function testFunction3() {
	transaction {
		local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},true);
		local.person.setFirstName('Jane');
		transactionrollback();
		assertEquals('Jane',local.person.getFirstName());
	}
	otherFunction3();
	assertEquals('Jane',local.person.getFirstName());
}

private void function otherFunction3() {
	transaction {
		local.person = EntityLoad('Person',{firstName='John',lastName='Doe'},false);
		assertEquals(1,local.person.size());
		assertEquals('John',local.person[1].getFirstName());
	}
}

Note that transactionRollback() does not rollback the change to the object, but it does appear to invalidate the cache. The second method gets a fresh copy from the database.

These gotchas can be very good things, but if you develop your application without being aware of them, you will be very surprised when data starts appearing in your database that you thought you had thrown away.

Architectural Mission pt 2 – At Your Service

June 23, 2011

Grandpa: Nothing gave Buttercup as much pleasure as ordering Westley around.
Buttercup: Farm boy, polish my horse’s saddle. I want to see my face shining in it by morning.
Westley: As you wish.
Grandpa: “As you wish” was all he ever said to her.
Buttercup: Farm boy, fill these with water – please.
Westley: As you wish.
-The Princess Bride

Here to serve.

That sounds fantastic when somebody says that to me. It’s a bit harder for me to say that even though I know full well that when I serve others I usually benefit greatly if not more than the one I’m serving. My focus is not about you or me but about software. Software that can be a service to others.

Service Oriented Software – got it. SOA, SaaS, ASP (not that one, the other one*), ESB, EJB, ORB, CORBA, COM, ETC.

Wow, really!? …and that’s just scratching the surface. This is not a new idea by any means. There seems to be an ebb and flow to centralizing and decentralizing the elements that make up a given application. What I have found is that in and of themselves they are neither right nor wrong. They are what they are. It’s for a given context that a level of appropriateness comes to play. Hardware capabilities, intranet and internet speeds and accessibility, user expectations and usage patterns. These all start telling a story and create a setting in which to place an application.

Distributed applications are cheered and jeered at the same time. Sometimes by the same people. They represent an incarnation of DRY (Don’t Repeat Yourself). As such they can be awesome. “You need widgets? Call the Widget Service!” The ease in which you can get data and functionality can be very impressive. Pulling an application into a hundred remote calls can also be something else. Slow.

If you have a single application it may not make sense to go the SOA route. You can still design and build this way to think separate but deploy combined smartly making everything a local call without the over head of serialization. This pattern really works best to serve multiple applications that have shared needs or need shared data.

If the functionality is not intended to be shared with multiple applications do not make it a service. Don’t pull in consultants and fire up a major ESB project with crazy orchestration to negotiate and transform data between disparate systems when there’s only one consumer. We’ll talk more about application design another time. Right now I’m focused on services.

What is a service?

To me it’s just an application. Instead of the consumer being a user it is another application. It’s also data with behavior. Hey… that sounds like encapsulation from the OOD school. Go figure. It is. At it’s core SOA is a very Object Oriented approach to designing an application. This is why you can design this way regardless if you’re deploying as a separate service or as an integrated business unit within your application. You should be thinking this way already. We’re just gonna pull part of the application out so others can call it without:

1. Copy and pasting the original code (bad coding practice fraught with maintenance issues)
2. Making a static reference to your application (inappropriate coupling)

This service should offer value. It should be strongly cohesive and fully encapsulated. The service should only do what it is named to do. A ‘beach finding’ service should not know anything about gas stations. It knows beaches. You should not have any beach logic in your application, it’s in the beach service. If you want to know where it is ask the service. If you want to know how popular it is ask the service. If you want to know how to get there… ask the mapping service, the beach service doesn’t understand directions.

I like to think of services as Legos. Very simple to use and combine. By connecting a few together I have a working application. That’s when the magic happens. The real benefit is that the service is independent of your application and has it’s own delivery and maintenance schedule. If it’s tested and solid that part of your app is already done. Don’t do it again. It’s free for everybody after the first consumer. When your library is big enough you can build a robust new application quickly and primary focus on the business needs at hand. That’s adding value!

From a deployment standpoint I like my service layer to be out of the DMZ and locked up tighter. It’s an extension of your data and is equally sensitive. Lock it up and protect it as best you can. Sure this is a hardware issue but at some point we’re going to actually deploy something on a real box and it’ll be subject to real users in the real world. I recommend doing a security audit periodically so you know where you stand.

If you’ve followed our RESTful talks you should already be thinking of making RESTful services. Keeping them stateless will allow you to load balance and scale this tier as needed with minimal effort. Be careful as you may be stateless but if you’re caching data (yeah, yet another topic to dig into) make sure you’re either caching that externally or have a way to synchronize.

I’d be remiss not to state that your RESTful service should probably return plain text JSON constructs. They’re so easy to use these days. Most languages have utilities available to generate and consume JSON so you don’t even have to sweat this one. So you’re service can now be consumed by anyone, anywhere, and… wait. No, I don’t really like that all that much. I’m going to go back to locking up my service tier. If I really want this exposed externally I recommend creating a gateway application to handle those chores. Keep your tiers intact, and in ship shape. You’ll do just fine.

“I am Juan Sánchez Villalobos Ramírez, Chief metallurgist to King Charles V of Spain. And I’m at your service.”
-Highlander

*ASP is an acronym that meant “Application Service Provider” before “Active Server Pages” from Microsoft came along.

Architectural Mission pt 3 – Bottoms Up!

June 23, 2011

Previously I’ve mentioned that we’re on a mission (part 1, part 2). We’re instituting a new platform. A central part of this initiative is a remote service layer available to all of our applications. There is a lot of talk out there about services, orchestration, and RESTfulness, but who’s talking about what is IN that service?

Me, that’s who. Buckle up as we’re about to begin part 3 of our journey!

I was originally going to discuss the dangerous phenomenon of scope creep. This is the result of the scope of a project being expanded over its lifecycle. While this is indeed something to watch for, and can lead to disaster, I’m going to go in a different direction for this entry. Recent conversations within our team brought to light a more poignant topic. One that still gets to the heart of the matter I wanted to address!

“It is not the mountain we conquer but ourselves.” – Edmund Hillary

Top-Down vs. Bottom-Up design strategy.

Top Down means to start with the business use case and break it down into parts and implement those parts. From a services standpoint this would mean once the application has defined what it needs appropriate services are created to satisfy those needs.

This is where you’ll see odd service names, or service names that mirror business units. You’ll also see something else if you look closer. Methods that don’t quite fit together. If you take the business use case out do the calls seem to be a jumbled mess? Do they cross specific areas or domains?

Let’s define some more terms:

Separation of Concerns
This is the practice of ensuring there is minimal to no overlap in functionality between any two systems – in our case applications and services.

Areas of Responsibility (AOR)
This is a military term that defines a geographic area that a commander has authority over. For our purposes that refers to logical concepts and models and which application or service is the commanding officer.

If the only things that makes the individual method calls make sense is the common consumption by a single application you have a warning sign. Break the key ideas into groupings. These groupings can lead you to see the real AOR’s.

Something that may not be visible, and it one of the harder ideas to grasp is what you’re missing with Top Down design. You can meet the needs as requested and be successful. You had a request and you responded. Huzzah. You consolidated logic and optimized performance. You’ve applied caching and load balancing and have a robust system. These are all incredibly valuable and worthy in their own right… but would you believe that there’s more?

This is where Bottom Up design comes in.

Step away from the originating application and become the service. You really need to step into these shoes and now look at the world from this point of view. Ask the hard questions! Should my Beach service respond with ratings? Yeah, that makes sense. It’s information that is very specific to the beach. When I want the rating I’ll most naturally want to start there to see if I can find this data.

Should it respond with directions? Should it contain it’s own address? Oh, now we’re approaching the grey area.

How many other objects have an address? How many other objects will need to find directions? These concepts are related to the beach, but are not in the beach’s domain. I recommend keeping them out.

The beach can have a URI to an address object served by the address service. This is logical. The address service can return latitude and longitude coordinates. This is also logical. And the mapping service can give me directions, even if that service is really just Google Maps. Does Google know about my Beaches? Anything about my rating scheme? Nope, it doesn’t have to and is more powerful because it doesn’t.

Fiercely protect what is and is not in the domain of each service. When you do this something grand can now occur. Emergent applications.

When your services are designed to meet the applications needs, and yet remain flexible and locked into a core definition of what that service represents. It can be used by others. Used in ways that you didn’t design. This is the critical part. If you create a Bucket service intended to be used at the beach you could have success defining how much sand it can hold. But what a missed opportunity. The service that simply defines the bucket and rules for the bucket is more powerful. If that Bucket can be used to hold water, oil, rocks… whoa. How about turning it upside down to be stacked! You didn’t think of that one, but the service should. Not. Care. Define the entity and let the use case and applications define the rest.

In OOD terminology the service is the abstract class and the usage is the concrete implementation.

A system of services that can be leveraged for uses beyond their design. New concepts and ways of assembling applications that were previously impossible. This is what we’re doing. We’re starting to see the potential. We’re fighting for the services because they can’t fight for themselves.

“Tough times never last, but tough people do.” – Robert Schuller

Hold onto the vision, guard and guide it. Success is out there. Bottoms up!

Architectural Mission

June 15, 2011

Elwood: It’s 106 miles to Chicago, we got a full tank of gas, half a pack of cigarettes, it’s dark… and we’re wearing sunglasses.
Jake: Hit it.
-The Blues Brothers

I’m on a mission. I’ve been tasked with stewarding a new paradigm in how we build our software here at Lampo. There are many facets to this and being inspired by Kevin’s recent posts I, too, am going to try exposing the process as I go through it. I welcome you to join me on my journey and hopefully we’ll learn something along the way.

A new paradigm.

Have you introduced something new to your organization? It can be met with criticism or fanfare… or both. I’m fortunate to work at a company that believes in the book Who Moved My Cheese. This is required reading for our employees. The essence is that change is inevitable and there are ways to enjoy this process. I recommend reading this lil’ classic if you haven’t already. Some change ends up moving a lot of cheese. Changing fundamental architecture of all applications falls into this bucket.

What is this change?

Simply put we are moving to a service oriented architecture. That’s overly simplified and doesn’t encompass the whole strategy. “One Platform” is more like it. Our existing software is not bad by any means. There’s nothing fundamentally wrong with it. It’s exactly what has made us successful. If you’ve ever had the thought of changing how things are take a moment to remind yourself that your company’s success is based on the state of things today. It’s successful. The new change is untested, and high risk. Proceed with caution!

Why change?

Yes we have been successful. Our current apps have brought us to where we are. Will they get us to where we want to go? No. We’re growing and are experiencing growing pains. This is where change comes in!

We have a fair number of applications. We also have a fair number of capabilities that are similar across many of these applications and are not truly specific to any one app. This includes, but is not limited to concepts such as handling content, managing users, security, user interface and user experience. Kevin’s recent posts on Implementing Modular Web Design is talking about one of these new foundational concepts. We are very decentralized and desire to move to a centralized system.

We’re weaving SOA into our fabric because it fits in with our objectives and our end goal to give hope. Always, always, always know why you’re in business and what you are trying to achieve. This change isn’t something we’re doing because it’s popular, or a great way to impress peers. We chose a direction that fit our team and fit our mission.

Fundamental changes are risky ventures. I’ve heard them called “science projects” and anyone bringing one up was asking for trouble. I’ve known some companies that have almost sunk their business with a “major re-write”. Embracing change also means to understand what’s at risk – both good and bad.

This type of open discussion has helped form our strategies around introducing these changes. This level of change is deep. It effects our estimates, project management, developer communication, code management, testing, deployment process, and governance. Risk management needs to be ever present when every stage of the development life cycle is effected.

Be Confident!

We have an amazing team. I’m confident in my teammates, the mission, and myself. I have no doubt we will be successful. I’m not going to measure success on adhering to a spec or standard on how to implement an SOA architecture. It’s about abstracting out common elements into a reusable toolkit in order to deliver better products quickly.

Elwood: It’s got a cop motor, a 440 cubic inch plant, it’s got cop tires, cop suspensions, cop shocks. It’s a model made before catalytic converters so it’ll run good on regular gas. What do you say, is it the new Bluesmobile or what? – The Blues Brothers

I’d love to hear about your experiences with change! Please respond below.

Grails and Rabbits

January 12, 2011

Tim: There he is!
King Arthur: Where?
Tim: There!
King Arthur: What? Behind the rabbit?
Tim: It *is* the rabbit!
-Monty Python and the Holy Grail

This. Is. Ridiculous.

After SpringOne I was anxious to try Grails with RabbitMQ on my own.  I downloaded the complete bundle for Windows and set it up.  I’ve never run an Erlang application so I felt a bit funny, but it was simple and painless.  I set an environment variable for Erlang (ERLANG_HOME).  Then I just hard coded a ‘base’ directory for logging and whatnot in Rabbit (server.bat).  Yeah, I could have set another env var there too, but I was too anxious.

I started the server.bat file and had RabbitMQ running.  Though it was lonely.

Sir Bedevere: Well, now, uh, Lancelot, Galahad, and I, wait until nightfall, and then leap out of the rabbit, taking the French by surprise – not only by surprise, but totally unarmed!
-Monty Python and the Holy Grail

I jumped into STS and ran ‘install-plugin rabbitmq’
A simple config setting (Config.groovy):

rabbitmq {
   connectionfactory {
      username = 'guest'
      password = 'guest'
      hostname = 'localhost'
      consumers = 5
   }
   queues = {
      jimski()
   }
}

My Controller only needed to call:

rabbitSend 'jimski', msg

…and for fun I setup a Service to pull messages off the queue:

static rabbitQueue = "jimski"
void handleMessage(msg) {
   println "received message: $msg"
}

Voila! Messages taken in by the Controller make a call to rabbitSend and magically the Service sees them and pulls them out to display.  Crazy easy.  Crazy cool.

I’m going to keep at it.  Let me know your experiences with queuing.

Add Spring Security to ColdFusion

January 10, 2011

We are evaluating Spring Security as a part of our authentication and authorization platform. Since we have many ColdFusion apps, it was natural for us to see how it would work in tandem with ColdFusion. Fortunately, since ColdFusion is a Java web application, Spring Security fits right in.

In this post, I’ll show the basics of connecting Spring Security with ColdFusion. I’m not intending to teach how Spring Security works or other details of implementation. For more information, see the Spring Security Reference Documentation (also available as a PDF).

At a high level, you add Spring Security as a Servlet Filter that is setup to run before the ColdFusion servlet in the Java web application config file (web.xml). To make it as easy as possible to see how it works, I’ll show you how to to setup the Spring Security tutorial app. I’m starting with a new install of ColdFusion 9.0.1, installed as a J2EE app under Tomcat 6.0.29 (running on JDK 1.6.0.22, 64-bit on Windows XP Pro).

  1. Download Spring Security from here (using version 3.0.5, the latest as of this writing).
  2. Extract the zip file (spring-security-3.0.5.RELEASE.zip).
  3. Extract the tutorial WAR file located in
    spring-security-3.0.5.RELEASE/dist/spring-security-samples-tutorial-3.0.5.RELEASE.war
    to a local directory (I’ll call it <tutorial-war>).NOTE: If you’ve never run the Spring Security tutorial, you can just put the <tutorial-war> directory into the /webapps directory of your Tomcat app server and run it. Here is more info about Spring Security tutorial.
  4. Copy all of the .jar files from:
    <tutorial-war>/WEB-INF/lib
    into:
    <cf-app>/WEB-INF/lib
  5. Copy the file:
    <tutorial-war>/WEB-INF/classes/log4j.properties
    to:
    <cf-app>/WEB-INF/classes/log4j.properties
  6. Copy the file:
    <tutorial-war>/WEB-INF/applicationContext-security.xml
    to:
    <cf-app>/WEB-INF/applicationContext-security.xml
  7. Copy indicated lines from:
    <tutorial-war>/WEB-INF/web.xml
    to:
    <cf-app>/WEB-INF/web.xml 

    1. Under the line:
      <description>Adobe ColdFusion 9</description>
      (line 5 in my stock CF9 web.xml), insert the <context-param /> blocks from
      <tutorial-war>/WEB-INF/web.xml
      (NOTE: In the code below, I removed the first line in the first <context-param /> from the tutorial that said
      classpath:applicationContext-business.xml.):

      	<!-- INSERTED FOR SPRING SECURITY -->
      
          <!--
            - Location of the XML file that defines the root application context
            - Applied by ContextLoaderListener.
            -->
          <context-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>
      			<!-- REMOVED classpath:applicationContext-business.xml -->
                  /WEB-INF/applicationContext-security.xml
              </param-value>
          </context-param>
      
          <context-param>
              <param-name>log4jConfigLocation</param-name>
              <param-value>/WEB-INF/classes/log4j.properties</param-value>
          </context-param>
      
          <context-param>
              <param-name>webAppRootKey</param-name>
              <param-value>tutorial.root</param-value>
          </context-param>
      
      	<!-- END INSERT FOR SPRING SECURITY -->
      
    2. Under the many <context-param /> blocks and before the <filter /> blocks (around line 64 in my stock CF9 web.xml), insert:
      	<!-- INSERTED FOR SPRING SECURITY -->
      
          <filter>
              <filter-name>springSecurityFilterChain</filter-name>
              <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
          </filter>
      
          <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
          </filter-mapping>
      
      	<!-- END INSERT FOR SPRING SECURITY -->
      
    3. Under the <filter-mapping /> blocks and before the <listener /> blocks (around line 167 in my stock CF9 web.xml), insert:
      	<!-- INSERTED FOR SPRING SECURITY -->
      
          <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>
      
          <listener>
            <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
          </listener>
      
          <listener>
              <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
          </listener>
      
      	<!-- END INSERT FOR SPRING SECURITY -->
      
  8. Now, we have to adjust ColdFusion’s logging configuration so that Spring Security’s configuration and libraries are favored.
    1. Rename the file:
      <cfapp>/WEB-INF/cfusion/lib/commons-logging-1.1.1.jar
      to:
      <cfapp>/WEB-INF/cfusion/lib/commons-logging-1.1.1.jar.bak
    2. Rename the file:
      <cfapp>/WEB-INF/cfusion/lib/commons-logging-api-1.1.1.jar
      to:
      <cfapp>/WEB-INF/cfusion/lib/commons-logging-api-1.1.1.jar.bak
    3. Rename the file:
      <cfapp>/WEB-INF/cfform/jars/commons-logging.jar
      to:
      <cfapp>/WEB-INF/cfform/jars/commons-logging.jar.bak
    4. Rename the file:
      <cfapp>/WEB-INF/cfform/jars/commons-logging.properties
      to:
      <cfapp>/WEB-INF/cfform/jars/commons-logging.properties.bak
    5. Create the file:
      <cfapp>/WEB-INF/classes/commons-logging.properties
      , and insert the following into it:

      	org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.SLF4JLogFactory
      	org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
      
  9. Extract the file security.tld from the META-INF directory of the file
    <cfapp>/WEB-INF/lib/spring-security-taglibs-3.0.5.RELEASE.jar
    and put it into the
    <cfapp>/WEB-INF/lib
  10. Edit the file:
    <cf-app>/WEB-INF/applicationContext-security.xml
    and comment out the <session-management /> block (around line 35), like so:

    	<!--
    	<session-management invalid-session-url="/timeout.jsp">
    		<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
    	</session-management>
    	-->
    
  11. That should be all of the server-side configuration you need to make Spring Security work with ColdFusion. When you startup your app server, you should see a lot of Spring Security related output in your console, ending with:

    Root WebApplicationContext: initialization completed in  ms

    Since you can use JSP Tag Libraries in ColdFusion templates or CFCs, you can import Spring Security’s taglib and then easily restrict access to certain content or code using Spring Security’s access expressions. Here’s an example CFM file.

    <cfimport taglib="/WEB-INF/lib/security.tld" prefix="security">
    <html>
    <head>
    	<title>Spring Security on ColdFusion tester</title>
    </head>
    <body>
    	<h1>Spring Security on ColdFusion Test Application</h1>
    	<cfinclude template="/include/nav.cfm" />
    
    	<security:authorize access="isAuthenticated()">
    	<p>You can see this because you are authenticated.</p>
    	</security:authorize>
    
    	<security:authorize access="hasRole('ROLE_SUPERVISOR')">
    	<p>You can see this because you have supervisor permission.</p>
    	</security:authorize>
    
    </body>
    </html>
    

    That’s just the beginning — but a pretty strong beginning that opens up a whole new world of enterprise-class security.

Asynchronicity

December 21, 2010

“Daddy grips the wheel and stares alone into the distance.
He knows that something somewhere has to break” – The Police

I recently attended SpringOne 2GX and had a great time.  The folks behind Spring, Groovy, and Grails are fantastic.  Go find a NFJS event and be dazzled.  During one session I learned about RabbitMQ, a recent acquisition of SpringSource.  This is an impressive project done in only 12,000 lines of code!

I’m greatly intrigued by a message queuing system.  My only experience is as a gateway to a mainframe system.  Not exactly a keen architectural strategy as much as “that’s how you gotta do it.”  So I’ve seen something there, but have struggled to find a good use.

But I feel like I’ve found something!  We have many applications that have a common need to interface with an external system via SOAP.  This is an expensive operation and is currently handled synchronously.  Ah HA! Toss it behind a queue and make it asynchronous and regain some performance.  This call doesn’t need to have a response so the application doesn’t have to wait for the return!

Now throw in other ideas like an enterprise language-agnostic logging system, and step that up a bit with a destination for critical errors  to be stored for investigation and triage.  I think I now have a trifecta of ideas, and enough critical mass to justify revving up a new service!

What are your thoughts and experiences with asynchronicity?

Code Wants to be Stoopid

October 27, 2010

Clever code never did no-one nay but no good.  Not know-how, not no-way.

Yeah, I’m not sure what I just said either.  I do know that “clever” and “slick” are words that I don’t care to hear about code, or a coding solution to a given problem.  Code needs to be simple.  How simple?  As simple as possible [but no simpler, yadda yadda yadda].  “But my code IS simple” you say.  I’m done.

Cool.

…just one more thing.  Do all your methods only do one, and only one, thing?  Yes, I said all.

Every method (or function) should accomplish only what it’s name says it does.  If you have a method “saveThing” it should only save that thing.  It should not check for something else, optionally set a flag, make any other call, then save that thing, and return the price of tea.  It should only save the thing.  This means you will have many very small methods.

At a high level this will lead to something really powerful:  Readable code.  You see, as your fine granularity builds upwards you are essentially utilizing the ‘composition design pattern’ in a micro-economy.

What are some signs that you may have code that can be refactored into it’s own method?

  • Length.  If a method is growing beyond 10 lines, take a close look and make sure it’s still doing only one job.  As methods grow they want to do more than they should.  You can’t convince me that 1,000 line method is as small as it can get.
  • Unused parameters or only using one or two variables off an object.  Too much data will lead to putting process in the wrong place.  If you don’t have the data you can’t do the wrong thing with it.  Don’t pass in a few extra objects just in case.  If you don’t need them pull them out.  Use static analysis to remove unused and dead parameters (and code blocks).  If you really only need to do work on a username… just pass in the string, and not the whole user object.
  • Comments.  If you feel the need to explain a section of code inline, it should be it’s own function with a well suited name.  You either use too many comments (rare, and not cool but that’s another topic) or you use one or two in confusing places.  That’s the tingly feeling you’re trying to learn that says “put this code in it’s own method”.

This is the path to better code.  Code that does what it says it does, nothing more and nothing less.  It sounds so simple, but is the essence of a truly powerful system.  Keep your code dumb, you’ll thank me for it.

P.S.  I know it’s spelled “stupid”.  😉