The amazing adventures of Doug Hughes

Archive for September, 2008

Creating a Web Service in ColdFusion

This is a quick blog entry to answer a question I received by email. Here’s the question:

I am a final year Computer Science and Engineering student. I have planned to implement and deploy a Web Service for my final year project. I couldn’t find a good tutorial for creating a Web Service with ColdFusion. It would be very kind of you if you can suggest me what to do, or if you could refer me to some tutorial which is available for download.

Honestly, I debated whether or not to blog this answer. This is the kind of topic that bloggers were writing about when ColdFusion MX came out many years ago. That said, sometimes old topics need to be rehashed for those newer to ColdFusion. (In other news, there are programmers who are new to ColdFusion!) Anyhow, to actually answer the question, creating web services in ColdFusion is painfully simple. All you do is start out by writing a CFC. For example, this hello world CFC:

<cfcomponent>
    <cffunction hint="I say hi!" name="sayHello" returntype="string">
        <cfargument default="world" hint="Whom to say hi to." name="to" required="false" type="string"/>
        <cfreturn "Hello, #arguments.to#"/>
    </cffunction>
</cfcomponent>

This component, should you instantiate it and call the sayHello method will return a string saying hello to whatever you tell it to. The question of the moment is how to make a web service that will remotely expose this method? By default, all functions in ColdFusion components are public. This means any code in your application can instantiate the component and call the method. Other options are private, protected, and remote. I’m going to ignore private and public and hone in on remote. If you set the access to remote you are allowing anyone in the word to execute that method as a web service. Here’s the updated code:

<cfcomponent>
    <cffunction access="remote" hint="I say hi!" name="sayHello" returntype="string">
        <cfargument default="world" hint="Whom to say hi to." name="to" required="false" type="string"/>
        <cfreturn "Hello, #arguments.to#"/>
    </cffunction>
</cfcomponent>

That’s it! That’s all it takes. To actually use this web service simply browse to the path to the CFC over the web and append “?wsdl” to the end of the request. For example: http://somesite.com/helloWorld.cfc?wsdl. At this point you have a WSDL file and can use that for remote requests.

The First Reactor Meeting

As I stated a few days ago, I’m handing the reigns of Reactor project management to the esteemed Mark Drew.  As a part of this hand off to the community, Mark and I have decided to hold bi-weekly meetings to discuss the state of Reactor and steer the project.  Today was the first Reactor project management meeting and I think it went well, if I do say so myself. We started out with some confusion over whether or not we should use the voip features in the Connect room generously provided by Andy Allan.  The short answer is no, it’s terrible.  So we’re going to try to work out a bridge between Skype a US based conference line.  That way we can all dial in and talk for free.  On the other hand, once we gave up and chatted in Connect the meeting actually went quite well.  So, we’ll get that worked out somehow. In the meeting we discussed a number of topics and came up with a list of action items which we assigned to various people.  The outcome of the meeting is documented here.  We also came up with a few points to discuss on October 8th which are outlined here.  At this point things are rolling again.  Those who are in on the action will take our steps and in two weeks we’ll figure out what to do next.  Please join in and help us make this process a success!

Alagad Needs a Part Time Programmer

I’m in need of finding a junior programmer who is willing to work part time for Alagad. Essentially, what I’m looking for is someone who is either currently a student and who wants experience or a junior programmer who wants to make some extra cash on the side. If this person does well, then I’d hope to hire them full time to work with the Alagad team next year.

This person’s time will be split between answering tech support requests and working on new Alagad products and internal projects. Tech support is currently a very small fraction of this time. This person should know ColdFusion and have a reasonably good understanding of CFCs, as this will be the primary language and technology they’ll be working in.

I’m also looking for some knowledge of HTML, CSS, JavaScript and other web-related technologies. Again, this position would be a part time contract position. I’d rather have someone who can work during the day, if possible, but I’m also happy to consider those who can only work nights and weekends.

If you’re interested in this position please send me an email at dhughes@alagad.com explaining why you’re the person for the job. In the subject of your email please be sure to use the word “aardvark”. Seriously. Extra points for creativity. (I use this to filter emails and get a sense of your creativity.) Don’t forget to attach your resume too, but be aware that I give a lot more focus to cover letters than resumes. I hope to hear from you soon!

When is coupling OK? Frameworks & Services & Applications… oh my!

The ModelGlue list had an interesting question come up this week. “Interesting questions” on lists are the primary source of blog fodder for me, mostly because I find myself writing responses that are worth reformatting a bit and posting to the blog… and such, honestly, is the case here. The individual in question was asking whether using the new beans=”” attribute in ModelGlue:Gesture controllers would couple your application too tightly to the framework and therefore shouldn’t be used. Before I get into the answer, however, a brief aside:

For those not-in-the-know, adding the beans=”” attribute to the cfcomponent tag of an application controller in MG:G, and providing a comma-delimited list of bean IDs from the ColdSpring file (you are using ColdSpring, right?) will automatically pull those beans from ColdSpring and compose them at variables.beans.beanName.

Example:

<cfcomponent extends="modelglue.gesture.controller.Controller" beans="UserService">
	<cffunction name="getUser">
		<cfargument name="event" />
		<cfset event.setValue("User",variables.beans.UserService.getUser(event.getValue("UserID"),0)>
	</cffunction>
<cfcomponent>

So the question was basically, “Does using the beans injection functionality in MG 3 couple your application to the framework?” and by extension, “Does using a framework’s features inextricably marry your application to the framework?” and applies to about any application framework out there. The short answer is, well, really… yes and no.

The use of anything that extends modelglue.gesture.controller.Controller definitively binds your application to the framework in question. However, since you’re only going to be extending the MG core controller class when you’re building your own controller in a ModelGlue app, it’s a moot point… using the built-in bean injection is just using a feature of the framework when you’re building an application that uses the framework.

In other words, yes because you’re building a ModelGlue application at all, and no because using bean injection doesn’t couple you to the framework any more than the rest of the application does. Where you wouldn’t want any reference to the framework is actually one tier below the controller layer… your service layer. At least in theory, your controller talks to services and services talk to everything else.

Let’s look at a psuedo-codish method you might find in an MG controller:

<cffunction name="saveUser">
	<cfargument name="event" /></p>
	<cfset var UserID = event.getValue("UserID",0)>
	<cfset var userName = event.getValue("userName","")>
	<cfset var emailAddress = event.getValue("emailAddress","")>
	<cfset var password = event.getValue("password,"")>

	<cfset var result = variables.instance.userService.saveUserProfile(UserID,userName,emailAddress,password)>

	<cfif result>
		<cfset event.addResult("saveSucceeded")>
	<cfelse>
		<cfset event.addResult("saveFailed")>
	</cfif>
</cffunction>

From this we can extract a few observations and parse them into a couple rules of thumb that I use to keep my own mind pointed in the right direction as I develop applications (not counting laziness, client expectations, and/or anything else that may cause me to randomly break my own thumbs):

  1. What goes on in the service layer is effectively hidden from the controller and therefore the service methods can be used to very simply service a Flex application, an application using a different framework, or ad-hoc code. Using ColdSpring to manage your service-layer allows you to use AOP and provide your service layer to Flex, AIR and AJAX applications very easily and passing discrete arguments into service methods keeps things nice an speedy and prevents things like “infinite composition” in objects… an ugly thing that I’ve seen cripple Flex development.
  2. Controller methods accept an event object as their sole argument. It contains all the data from the form and URL scopes as well as anything injected into it via onRequestStart events (often application constants get stuck in the event object for convenience).
  3. Service-layer functions take discrete arguments relevant to whatever objects they’re dealing with… so while in this example, saveUserProfile(userId,username,emailAddress,password) is called with discrete arguments extracted from the event object you could (were you to be lazy and like to take chances with your apps) call saveUserProfile(argumentCollection=event.getAllValues()) and have done with it.

On the other hand, though, passing Transfer (or Reactor, or your own Model) objects from the service thru the controller into the view makes a good many things a great deal easier. So having userService.getUser(userID) return a User object that’s then stuffed into the event object is fine… so your controllers can then use things like makeEventBean() and stuff which simplifies somethings and makes others more difficult.

In the end, though, the goal is to make your service layer be totally independent of any other facility, and as long as you’re doing that then using specific features of the application framework of your choice when you’re creating the application does nothing to couple the service and persistence layers (or the model) to the framework. Do that and you’ve truly achieved a decoupled service layer and model and when you get around to releasing the full-featured Flex version of the application you’ve already done at least 75% of the work!

The Future of Reactor

Wow, when was the last time I blogged anything about Reactor? According to my blog archives that would be almost a year ago. So, the natural question arises, whats happened in that time? Sadly, not much. Which is exactly what this blog entry will begin addressing. Last week I sent an email to the reactor mailing list regarding the future of Reactor. In this email I essentially pointed out what the community has known for quite some time. Namely, that Reactor has been quite stagnant for quite a while. In fact, Reactor stalled right before it reached 1.0 and has been labeled a Release Candidate for a very, very, long time. So, whats the cause of this? In a nutshell: me.

The rise and stall of Reactor corresponded with the Rise and (thus far) success of Alagad. I can not manage both the demands of developing, documenting and supporting Reactor while also growing Alagad. Now, before I make my big announcement, I would like to defend Reactor. We have been using Reactor here at Alagad for years. Furthermore, there are nearly a thousand people on the Reactor mailing list. I personally believe Reactor is 1.0, except for the documentation that is seriously lacking.

Some people have postulated or assumed that the success of Transfer has meant the death of Reactor. This is untrue. There are many people who feel that Reactor brings something different to the table that they prefer. Then, theres the question of Hibernate integration in ColdFusion 9. Should anyone dedicate cycles to developing Reactor when Hibernate will be integrated into ColdFusion 9? In my opinion, yes, for a few reasons.

First off, as much as we all love Adobe, how many times have you been burnt by bugs or incompleteness in new ColdFusion features? Adobe does a great job with ColdFusion, but they only seem to complete 80% of what I need in new features. Thus, I dont trust that Hibernate integration in version 9 will ready for prime time at first. Beyond all that, Ive been told that Reactor is the only ColdFusion ORM framework that works on Railo, though I dont know how true that is.

I think there is a bright future for Reactor, if we could just get the project moving again.

And so, over the last few months Ive been pestering Mark Drew of CFEclipse fame to take the mantle of Reactor Project Manager. Finally, last week he acquiesced and agreed to take the help of the Reactor project. We vetted this decision through the Reactor mailing list and most people with an opinion supported the decision.

I will still be involved with Reactor but more as a proud parent helping his child enter the world on its own. Now, the question is, not only how to get Reactor moving again, but where to take it. To answer that question, weve have decided to hold public planning meetings every Wednesday from 12 noon to 1pm EST time. The meetings will be held in Andy Allans Connect room at http://connect.reactorframework.com.

Anyone who wishes may attend these meetings to chip in and help steer the project and volunteer to help. The first meeting will be held this week, September 24th and will primarily be organizational. Well probably spend some time attempting to figure out where to take Reactor and creating some tasks we need to accomplish and, hopefully volunteers to help with those tasks.The next week well meet, check our progress and establish more goals. Rinse, repeat. Im not sure where this will take Reactor, but, with a little perseverance and a little luck, hopefully it will be someplace good. I hope to see you Wednesday.

What is a DSL?

Peter Bell has been talking about domain specific languages for some time now, but I expect they are still a pretty foreign concept to many people, myself included not too long ago. However, if you have used any of the popular ColdFusion frameworks like Model-Glue, Mach-II, ColdSpring, etc., then you have actually used a DSL in their XML configuration files.

To my current understanding, a DSL allows you to take a generic set of application code and configure it to a specific use – hence the words domain specific. That configuration may be done via XML, a text file that is parsed, or even code. The big thing here is that you are writing configuration for a specific problem area or domain.

On a recent project, we were faced with 50+ simple CRUD style lookup tables that all had to have the same style list, create, and update form user interfaces. So, instead of creating individual little DAO, business, and service objects as well as the same cfm views over and over, we are adopting a generic “object” approach where there will be a single DAO, business object and service object, which when given an “object definition” via an XML document, will become smart objects and all of the sudden know that they represent a certain data element.

By doing this, the actual code we have to maintain is limited and making fixes and tweaks that much easier. The UI design is also much simpler in that there are only one set of views, so changing styles etc. can be done in one place and be applied across the board. It is also much simpler to make changes to the different objects managed by the system, whether that be adding a new object definition or changing the properties of an existing object definition.

So, are people using DSLs out there without really knowing it? What are some problem areas that you have addressed with a DSL? I know Peter Bell has discussion building whole applications before and while I am not to that point yet, I am very interested.

Delete Almost Everything From Your MSSQL Database

Ok, this script is dangerous. Use it only when you intend to. If you delete stuff you don’t want to, it’s your problem!

Anyhow, now that we’re past the disclaimer, I’m posting this blog entry as a follow up to one Layne Vincent posted earlier this week on how to truncate most of your tables. As it were, we are currently working on a project where pretty much everything related to the database is scripted. We have a script we generate that will completely rebuild our database including all of it’s tables, stored procedures, functions, basic lookup data etc.

The problem is, although the script has a chunk of code at the beginning to drop tables, the script takes no account of foreign key constraints and these drops simply don’t work. Besides, we also have a lot more than just tables we may want to drop. So, we were talking about this problem the other day and it got me thinking about a way to drop virtually everything from your database without actually dropping and recreating your database. (Why? Well, what if you don’t have rights to drop the database or create a new database?)

What I came up with was a simple script that will select most types of objects from the sys.objects view into a cursor. I then loop over the cursor and call the correct drop statement to drop the object. The query is sorted so that I can first drop foreign keys, then tables, then other objects. Without further ado, here’s the script:

/*** drop (pretty much) everything before rebuilding the database ***/
DECLARE
	OBJECTS CURSOR FOR SELECT
		so.name,
		so.type,
		so.type_desc,
		p.name AS parentName
	FROM
		sys.objects AS so
	LEFT JOIN sys.objects AS p ON so.parent_object_id = p.object_id
	WHERE
		so.schema_id = 1
	ORDER BY
		CASE
	WHEN so.type = 'F' THEN
		0
	WHEN so.type = 'TR' THEN
		1
	WHEN so.type = 'U' THEN
		2
	WHEN so.type = 'F' THEN
		3
	ELSE
		4
	END OPEN OBJECTS DECLARE
		@name AS nvarchar (MAX) DECLARE
			@type AS nvarchar (2) DECLARE
				@type_desc AS nvarchar DECLARE
					@parentName AS nvarchar (MAX) DECLARE
						@statement AS nvarchar (MAX) FETCH NEXT
					FROM
						OBJECTS INTO @name,
						@type,
						@type_desc,
						@parentName
					WHILE @@FETCH_STATUS = 0
					BEGIN

					SET @statement = '  IF(@type = ' F ')
BEGIN
PRINT ' DROPING FK : ' + @name + ' OF type ' + @type + ' (' + @type_desc + ') '
SET @statement = ' ALTER TABLE ' + @parentName + ' DROP CONSTRAINT ' + @name
EXECUTE(@statement)
END
ELSE IF (@type = ' TR ')
BEGIN
PRINT ' DROPING TRIGGER : ' + @name + ' OF type ' + @type + ' (' + @type_desc + ') '
SET @statement = ' DROP TRIGGER ' + @name
EXECUTE(@statement)
END
ELSE IF (@type = ' U ')
BEGIN
PRINT ' DROPING TABLE : ' + @name + ' OF type ' + @type + ' (' + @type_desc + ') '
SET @statement = ' DROP TABLE ' + @name
EXECUTE(@statement)
END
ELSE IF (@type = ' FN ')
BEGIN
PRINT ' DROPING FUNCTION : ' + @name + ' OF type ' + @type + ' (' + @type_desc + ') '
SET @statement = ' DROP FUNCTION ' + @name
EXECUTE(@statement)
END
ELSE
PRINT ' Didn 't drop object ' + @name + ' of type ' + @type + ' (' + @type_desc + ')'  FETCH NEXT
					FROM
						OBJECTS INTO @name,
						@type,
						@type_desc,
						@parentName
					END CLOSE OBJECTS DEALLOCATE OBJECTS

Tag Cloud