ColdFusion and Remote Calls and notifying the caller of the problem

I want to touch on a subject that I know that not many people actually take into consideration, and that is how to deal with errors and other problems on the server when being called by a remote client call.

I am going to state that I am defining any call made as either a web service, remote procedure call, rest calls that is either from a client like a JavaScript call or even Flash, Flex or anything else.

So how do we handle them, should we report them to the caller or should we just log the call somehow on the server.

One of the questions that I always take into consideration is notifying the caller as to what might have gone wrong. I see time and time again calls that are made to gather information via Ajax or any of the other methods listed above, that the error is never reported back to the caller.

Is it really that important?

Well yes it is.

Let us take into consideration that an application needs to make a call to your code, via what ever means that has been defined by your application, and the Application that is making the call gets no response back from the Remote Procedure. A lot of the time you just get an error on the server, that will hang the client. But I hear you say that I have the application set up to log the problem, well that is all good and everything, but what about the caller who has no clue as to what has happened on their end?

Well depending on the Application it might crash, or just hang and the user will never know that a problem has happened.

So what do we do about it, well there are a number of ways that you can approach this, and the easiest way that I usually implement is to return a structure that indicates the success or failure, along with information that can be displayed if the Application calling your application can then display if they so desire.

So lets look at say the creation of a user for example, and the calling code may look something like this.

<cffunction name="createUser" access="remote" output="false">
   <cfargument name="userData" required="true" type="Struct" />
   <cfset userService.createUser(arguments.userData) />
</cffunction>

Now the code is nothing special and it is basically calling a user service, which then takes the passed data and creates the user. But what if something goes wrong here, as far as the calling Application is going to be concerned is that the user was created. Now the things that can go wrong here, the user exists and or something in the database might fail and the client Application will never know.

But I hear you saying that the userService method createUser has all this being logged and emailed to a user, and then they can fix the problem if they need. Well I am sorry to say that this is just not enough, and if you think like this then you really are creating a headache for the calling Application, not to mention you really should be thinking more about others here. For any number of reasons, they will never know the user has not been created. And depending on what they need to do, then for all intent they will just assume that the user was created, until they run into other problems further on in their application.

So is there a solution, well there are actually a lot of solutions. But the one I tend to fall back on is passing back a struct of information so the calling application will know what has happened.

So if we take the above code we can do something like this instead.

<cffunction name="createUser" access="remote" returntype="struct" output="false">
   <cfargument name="userData" required="true" type="Struct" />
   <cfset var local = {} />
   <cfset local.response['status'] = 'ok' />
   <cfset local.response['message'] = '' />
   <cftry>
      <cfset local.response['message'] = userService.createUser(arguments.userData) />
      <cfcatch type="Any">
         <cfset local.response['status'] = 'failure' />
         <cfset local.response['message'] = cfcatch.message />
      </cfcatch>
   </cftry>
   <cfreturn local.response />
</cffunction>

Now this is not a big change here, and the important thing to note is the structure definition that is being returned. And this can be anything that you like, but the idea is that you allow the calling Application to know what has happened. So you can see that I am setting a status of ok or failure, and if there is a failure I am sending the details of the message back to the calling Application.

So if the user details that is being sent will throw a constraint violation because the username is the primary key, or that the information in one of the fields might end up being truncated, or any other problem that can occur. The calling Application will then know what has happened, and then can decide on to ditch the information or pop up a message saying that a problem has occurred.

I consider this to be a fundamental pattern in development of a life cycle, and it is just not good enough to just send an email of the problem. I have seen this time and time again where people have not thought outside of the situation, and what if this happens or what should we do if it does, and worst still I have even seen this removed in favour of an email instead. I fell over backwards when I saw this sometime ago, and the person who did it just wasn't aware why it had been placed there.

So if you find yourself in a situation where you are writing an API, or even remote calls to your application. Please do give some consideration on making the jobs of the developers on the other end a little easier, you never know it just might end up reducing your work load as well.


ColdFusion and Remote Calls and notifying the caller of the problem - http://t.co/0vAiI4h Aug 27, 2011
ColdFusion and Remote Calls and notifying the caller of the problem http://t.co/EvTieQZ Aug 27, 2011