Welcome!

ColdFusion Authors: Maureen O'Gara, Hovhannes Avoyan, Yakov Fain, Pat Romanski, Liz McMillan

Related Topics: ColdFusion

ColdFusion: Article

The Asynchronous CFML Gateway

A Real-World Example of a Great New Technology

This was still a less-than-ideal situation. I hope this doesn't come as a shock to any of you, but in case you were unaware, users can be impatient at times. No matter how many different ways I explained the situation, because most users are accustomed to clicking on a link and having the next page finish processing more or less instantly, some users just couldn't understand why generating 50,000 e-mails was taking so long.

Even with the addition of flushing each address to the screen, there were still occasional timeout issues that would cause the browser to throw an error of one kind or another. At a minimum seeing an error at the end of the batch would create a sense of uncertainty in the user's mind as to whether or not the e-mails were sent successfully. I thought about going to some relatively insane lengths to change this situation, but in the end I just stuck with the solution and dealt with continually educating my users on the process.

Asynchronous Processing to the Rescue
My wish for a better way of handling things in the E-Mail Blaster was answered with CFMX 7 Enterprise and the asynchronous CFML gateway. No longer do my users have to wait for each e-mail to be sent. Now I can just generate the recipient list, pass everything off to my e-mailer CFC via the asynchronous gateway, and immediately return a message back to the user informing them that their e-mail batch is in process and they will be notified via e-mail (and Lotus Sametime IM as well, but that's a story for another article!) when the process is complete. I also log each e-mail address to a text file as the e-mails are generated and attach this text log to the confirmation e-mail, so no longer do I have to respond to questions concerning whether or not a particular e-mail was sent to a particular address.

This is an amazingly powerful solution, and as usual ColdFusion makes doing powerful things such as this extremely simple. Let's walk through the steps involved with creating a CFC and registering it in the ColdFusion administrator so it can be used via the asynchronous gateway. (Just a reminder: event gateways are only available in ColdFusion Enterprise and Developer editions. Gateways are not available in ColdFusion Standard.)

Step One: Create AsynchE-mailer.cfc
This step was surprisingly easy. Since I originally wrote the E-mail Blaster when CFMX was first released I wasn't using CFCs very heavily at that point, so my e-mail sending code was in a simple CFML page. The actual code itself did its job well, however, so basically it was just a matter of some minor tweaks and pasting the CFML code into a new CFC.

In order to be able to use a CFC via the asynchronous gateway there is one key method that must exist in the CFC: onIncomingMessage. This function is what is called when SendGatewayMessage() is called from your ColdFusion application (more on this in a moment). The onIncomingMessage method in the CFC takes a struct as an argument, and this struct contains the information you want to use within the asynchronous CFC. In the case of the E-Mail Blaster, the struct contains the recipient list, the HTML contents of the e-mail, and a few other bits of information such as the administrator and sender's e-mail address and a path to which a log file is written. See Listing 1 for the complete AsynchE-mailer.cfc code.

Step Two: Register AsynchE-mailer.cfc in the Event Gateway Administrator
Once the CFC is created, registering it for use via the asynchronous gateway is a snap. First, log into the ColdFusion administrator and click on the Event Gateways link on the left. The Gateway Types area is where you define the various gateways to which the ColdFusion server has access, and you'll see that one of these is the asynchronous CFML gateway. You don't need to do any configuration on this page in the administrator, just be aware that this is where the asynchronous CFML gateway is registered with the ColdFusion server.

Click on Gateway Instances to be taken to the form you will use to configure the AsychMailer.cfc to run as a gateway. You'll see the following fields:

  • Gateway ID: This is the handle or name by which you will refer to the gateway instance in your ColdFusion code, and can more or less be anything you want. I named this gateway "Asynch E-mailer."
  • Gateway Type: This lists the gateway types that are registered on the server. In this case you'll want to choose "CFML - Asynchronous Events via CFML."
  • CFC Path: This is the physical path on the server to the CFC that you want to use as the gateway.
  • Configuration File: This tells ColdFusion where the configuration file for the gateway is, but we don't need one for this CFC so we leave that field blank.
  • Startup Mode: This tells the ColdFusion server whether you want this gateway instance to start up automatically (i.e. when ColdFusion starts), manually, or that the gateway is disabled altogether. If it's a gateway you're going to use in a production environment, obviously you'll want it to start automatically.
Once you have the information entered, click on "Add Gateway Instance" and after it the gateway instance is registered and starts up it's available to use from your application. With the setup work out of the way, let's take a look at the specifics of how we send our e-mail blasts asynchronously.

Step Three: Call the Asynch E-mailer Gateway from the E-Mail Blaster Application
Calling the asynchronous gateway is as simple as calling the SendGatewayMessage() function, which takes two arguments: the handle or name we gave our CFC in the ColdFusion administrator, and a struct containing the data that we want to pass into the gateway.

First let's build a struct to hold our data. Since we're using the gateway to send e-mails, the struct we pass to the gateway contains the recipient list, the HTML contents, the sender information such as name and e-mail, and a few other items used for housekeeping and error handling. This is just a plain old ColdFusion struct, so simply populate the struct in your CFML or CFC and pass it to the gateway. Since I've converted the original application into a more object-oriented model, I'm using an E-mailBlast Session bean to store the e-mail blast data prior to beginning the send process, so the code populating this struct looks like this:

e-mailBlastData.recipients = Session.e-mailBlast.getRecipientList();
e-mailBlastData.fromName = Session.e-mailBlast.getFromName();
e-mailBlastData.fromE-mail = Session.e-mailBlast.getFromE-mail();
e-mailBlastData.subject = Session.e-mailBlast.getSubject();
e-mailBlastData.content = Session.e-mailBlast.getContent();

Once the struct is populated, we simply make a call to the asynchronous gateway by using the SendGatewayMessage() function:

status = SendGatewayMessage("Asynch E-mailer", e-mailBlastData);

Taking another look at the AsynchE-mailer.cfc code, you will see that the gateway's onIncomingMessage function takes in a struct argument called CFEvent. You can call this anything, but CFEvent is the naming convention used in the ColdFusion documentation so I retained it here. Please note that once the struct is in the gateway, rather than calling the struct's members directly as you would in your application (e.g. e-mailBlastData.content) the struct members are called using CFEvent.Data.myStructMember notation. Using the previous example, the content data would come into the gateway as CFEvent.Data.content. Just be aware of the addition of "Data" to the struct.

More Stories By Matthew Woodward

Matt Woodward is Principal Information Technology Specialist with the Office of the Sergeant at Arms at the United States Senate. He was until recently a Web application developer for i2 Technologies in Dallas, Texas. A Macromedia Certified ColdFusion Developer and a member of Team Macromedia, he has been using ColdFusion since 1996. In addition to his ColdFusion work, Matt also develops in Java and PHP.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.