Thursday, 18 February 2016

Has your webservice code stopped working after ColdFusion10 because of Axis2 ?

In past few years I have seen many people struggling with their working webservice code which broke in ColdFusion10 onwards. Code works till CF9 but stops working since CF10 and they get errors like ServiceInvocationExcption or Axis2 AxisFault.

This happens because ColdFusion 9 introduced Axis2(Axis is the internal engine used in CF for SOAP based services) for their webservices. Axis1(the older version) is still available but is not the default one. This means that your existing code will now use axis2 engine by default. For most of the customers(I can assume 95%+) it works and performs better than previous versions but for some unfortunate of them it broke.

Here is what you need to make it work again.

Wednesday, 29 July 2015

CFB profiles and Preferences

CFB profiles and Preferences

Profiles is one of my favourite features of CFB3. It allows you to keep separate preferences as schemes(profiles we call it). For example when you are developing or writing code, you want to see your comments in yellow but when you demo your application you want to keep your comments in grey so they are not catchy. You don't have to change your comment colors always but you just have to switch your profile. To be specific you can maintain different color schemes, code-assist preferences, typing preferences, task tags, outline and syntax checking preferences with different profiles. For most developers modifying these small preferences increase their productivity, so trust me these are very helpful.

Here we will talk about how to maintain different profiles and also a bit about all these preferences that you can modify and play with and will be starting with Code Assist Preferences. To find them in CFB open Window->Preferences in your menubar. A preferences dialog will open. On left panel you have to reach to "ColdFusion->Profiles->Editor->Code Assist". On clicking it, in right panel you will see all related preferences.

Code Asisst:
For most of preferences, you will be able to understand what they do by their name, like in case of Code Assist they will help you modify what you see in code assist and how you get it and some related stuff.

Friday, 28 February 2014

CF New Mobile Project - Templates


You must be hearing about the mobile story in CF11, well yes, that is Huge. And if you haven't tried it yet, you are definitely missing a lot. Go on, try it but wait, don't you need a getting started tutorial. I bet you don't, only if you know that ColdFusion is providing templates for mobile project. Yes, you heard me right, templates. Isn't that great, you will get pre-baked code for your application. If you know what kind of application you want to create, just chose a template and wow! your application structure is ready. Alright, so now if you are interested enough to see how this works just read along otherwise still read along, I am sure you will feel like using it.

First thing first, this template feature is available in CFBuilder and being said that let me make you aware of the importance of CFBuilder3 with ColdFusion11. With CFB3 you will feel the actual power of mobile in CF11. Why is that? because with CFBuilder you can start right from scratch, use templates to create a mobile project, use builder's code assist to help you with new mobile functions, create a packaged application for iOS/Android, download it and install, DEBUG it from you device, inspect it with WEINRE and so much...

Now coming to the template feature, here are the steps you need to perform before you can try it.

Wednesday, 9 January 2013

Javascript Date Time parsing rules

Though these rules vary from browser to browser but still I am trying to put basic rules which are implemented by majority of popular browsers. To be on safer side please try these in your browser first.

JavaScript by default uses a simplified version of the ISO 8601 extended format to convert strings to Date objects

You can specify strings to construct Date objects either with Date(dateStr) or with Date.parse(dateStr). JavaScript first attempts to parse a date string by using the ISO format. If the date string is not in that format, JavaScript attempts to parse the date by using other date parsing rules.


The ISO format is a simplification of the ISO 8601 extended format. The format is as follows:

Friday, 13 July 2012

Axis-2 and Axis-1 compatibility issues

 Axis-2 and Axis-1 compatibility issues


Problem:

With ColdFusion 10 you can leverage power of Axis-2 WebServices. But you might get into issues if you are mixing Axis-2 with Axis-1. Axis-2 services are incompatible with Axis-1 services in ColdFusion because of the way their WSDL's are formed. Though by design Axis-1 and Axis-2 are compatible but in ColdFusion you might run into issues if you are using ColdFusion complex data types.

Since Axis-1 and Axis-2 are incompatible in ColdFusion, this means that if you are publishing your WebServices using Axis-2, then they should be consumed using Axis-2 only. Similarly if you are publishing your WebServices using Axis-1 then they should be consumed using Axis-1 only.

ColdFusion 10 Solution:

ColdFusion has taken all the measures to support backward compatibility with it's earlier versions. ColdFusion allows you to specify the version of Axis in which WebServices should be published or consumed. ColdFusion has given a control at three levels:

ColdFusion 10 WebServices - Axis2 vs Axis1

I have seen many people getting confused between Axis-2 and Axis-1 WebServices in ColdFusion 10. ColdFusion 10 has added the support for Axis-2 WebService, earlier till ColdFusion 9 only Axis-1 WebServices were supported.

So to begin with what exactly is this Axis-2 and Axis-1.

Intro Axis:
Apache Axis (Axis-1) is an open source, XML based Web service framework. ColdFusion internally uses Axis to publish and consume WebServices.  Apache Axis-2 is a complete re-design and re-write of the widely used Apache Axis but achieves same purpose. Axis-2 supports many new and flexible features over Axis-1 which means ColdFusion has implemented it not only to provide you latest features like Soap1.2 but also to give you more flexibility and power in your hand. You can always search for 'Axis-1 vs Axis2' if you want to study the advantages of Axis-2.


New in ColdFusion 10
 
 So let's see what ColdFusion 10 is offering with Axis-2

Monday, 18 June 2012

Node.js to ColdFusion - REST api


In my earlier post I explained how to expose a pdf service using ColdFusion REST api here.
In that post we saw that from the client side if I will pass a html document to this service it will convert it into pdf document and will return it back to the client. Also in my earlier post I gave an example to consume it using CF client itself. But there are times when your client side may not be ColdFusion. For that purpose I am giving an example to consume it using Node.js

Node.js server will act as a client over here and will contact ColdFusion to convert a document into pdf document.

Let's take a look at the code.

Sunday, 17 June 2012

ColdFusion html to pdf service - rest api


Convert a html document to PDF using ColdFusion <cfdocument> and REST power.

If you are not sure about how to start with REST, you can read my blogs here.

So let's write a CFC which will be exposed as pdf service using REST api.


Explanation:
Over here we have exposed a ColdFusion component as a REST resource - pdf, which will accept an html body and will return a pdf file in binary.

In the only function present, I am accepting POST request and will produce the content in "application/xml" format. POST request will be accepted because my httpmethod attribute in the function is POST and produces attribute is "application/xml" so it will produce xml content.

There is a point to note that even though I am producing xml content but still the produced string will not contain any xml tags. That is because ColdFusion only serializes the return variable in xml/json if it is complex variable like an Array, a Struct, a CFC etc.. As we are producing a binary which is a simple data type, so it will not be serialized rather will be returned as it is.

For consuming the data I am looking for argument in body of the request. Generally you will find the restargsource attribute present in <cfargument> tag to tell you where to look for the data. But if it's absent ColdFusion looks for the argument in the body of request.

Inside the function I am using <cfdocument> tag to convert the HTML body passed from client into PDF file. This PDF file will be saved in a variable name "pdffile" in binary format. And then returning this pdffile as it is in binary format back to the client.

Client side can be written in any language but here I will write an exmaple in ColdFusion itself.

All we need to do in client side is to call this service with POST http request and pass the HTML content in the body of the request.
..
In this example I am reading a html file from local directory and passing it's content to the service we just exposed.
And finally we are saving the result we have got back to sample.pdf

That's it. We are done.

Wednesday, 30 May 2012

ColdFusion 10 Chrome theme


If you are using Chrome, try this ubercool dark theme and stay close to CF 10.
How to use:
  1. Download ColdFusion theme from here.
  2. Save this file somewhere in your filesystem.
  3. Drag this file to your Chrome Browser.
  4. It will ask you to continue(left-bottom).
  5. Press continue and whola!!!
  6. To check open a new tab.
And ofcourse spread it if you like it :)

Thursday, 1 March 2012

my first REST resource



<- Previous Contents Next ->



PART-III
Tutorial on REST: First REST Resource(cfc)


In first part we saw a simple example on REST to start off the things. So moving forward I will give another very simple example and will explain it.



helloWorld.cfc
  1. Every component and every function acts as a REST resource(if you are publishing them). 
  2. A new attribute in cfcomponent 'restpath' OR 'rest' defines if a component can be published as a REST resource. Either of these should be present. 
  3. Attribute 'httpmethod' should be there in cffunction tag or cfcomponent tag. 'httpmethod' in cffunction tag overrides the one in cffcomponent tag. To publish/expose a function as resource, this attribute is necessary. Valid values for this are 'GET', 'POST', 'PUT', 'DELETE', 'OPTION', 'HEAD'. 
  4. Similar to 'httpmethod', 'restpath' can also be used in cffunction tag but it doesn't overrides the value of 'restpath' in cffcomponent tag , instead it appends to it. So if you want to call this function(resource), you need to give both the restpath's in URL. Check helloWorld.cfm's second http call for clearer picture
  5. Keeping other things simple like 'access=remote'(required for REST/WEB services) and 'returntype=string', lets see how can we call this service. 
Note: After writing a cfc(at-least one) in webroot, you need to register the folder(in which that REST cfc is present) as REST application, otherwise you will not be able to call any resource. Please check previous chapter for that.

helloWorld.cfm
  1. Considering that you registered this application with name 'IIT', the URL to access first resource(function HelloWorld) will be: http://127.0.0.1:8500/rest/IIT/HelloWorld
  2. So to access that resource all you need to do is, use cfhttp tag and call this URL. Keep in mind that method in cfhttp tag will match to the httpmethod present in function.
  3. Similarly to call the second Resource in cfc(function HiWorld), the URL will be: http://127.0.0.1:8500/rest/IIT/HelloWorld/HiWorld
  4. To call this from a cfm you need to call this URL using cfhttp tag with httpmethod as get.

how the URL works:

Breaking the URL for better understading
  1. http://127.0.0.1:8500/ - protocol//ip:port/
  2. rest/ - Compulsary string to call a REST resource. You can change this 'rest' string in server.xml and restart the server for changes to take effect.
  3. Examples/ - Mapping name you give to register an application using Administrator or restInitApplication method(Check next example for this) .
  4. HelloWorld/ - RestPath to call a resource. This was given as 'restpath' attribute in cfcomponent level.
  5. HiWorld/ - If your function also has a restpath then after giving a restpath for your component you need to give restpath for function also to call that function.


<- Previous Contents Next ->


Wednesday, 29 February 2012

Registering a REST application in ColdFusion10



<- Previous Contents Next ->



PART-II
Tutorial on REST: Registering a REST application



Regitsering a REST application
  1. To access any REST resource you need to register an application either through admin or using restInitApplication().
  2. Registering REST application is required because ColdFusion scans for all the REST resources present in directory you registered
  3. It is also important for you to know that you CAN NOT repeat 'restpath' for one and more resources. That is why it is a better option to create multiple apps, so that you can repeat the restpath in different applications as per your need
  4. You should also know that change in any resource(REST cfc) of your application will need a refresh in applcation. You can refresh from Administrator or using restInitApplication()


Using restInitApplication(): You can register as well as refresh an application using this method

This function takes three attributes: restInitApplication(dir_path, mapping_name, default)
    • dir_path: This is absolute path of the directory where you have plcaed your REST cfc.
    • mapping_name: This name can be anything. But keep in mind that this name will be used URL to call any of the resources in this application. Also note that this is an optional attribute. If this attribute is not present then ColdFusion will try to pick this name from Application.cfc(this.name) applicable to this directory.
    • default: You can get rid of the mapping_name in URL. To do so you can set any one of the application as default. I will discuss/explain this later with an example.
  1. If there is no error thrown, means your application has been registered successfully, so its always better to catch the error using cfcatch block
  2. If there is already an application registered with the mapping_name and the dir_path you gave, then this function will REFRESH already registered app.
  3. But if you will try to register another directory with already registered mapping name, you will get an error


Using Administrator: You can also register an application using Administrator
  1. Go to Admin -> DATA & Services -> REST services
  2. Root Path: Browse the directory which you want to register as REST application
  3. Service Mapping: Give the name of your mapping. This name will be used in URL to call any of the resource present in this application. This is optional. If not given, ColdFusion will try to search for name in Application.cfc(this.name) applicable to that directory.
  4. default: You can get rid of the mapping_name in URL. To do so you can set any one of the application as default. I will discuss/explain this later with an example


Application outside webroot
  1. You can also register a directory as REST application which is not present in your webroot
  2. To do so you have to add a mapping for that directory in ColdFusion
  3. Then you can register using the absolute path or also using that mapping instead of absolute path.



Default application:

If you really do not like to use the application mapping name(IIT - example from previous chapter) for you REST services, there is an option available to do that. But I will personally recommend that if you are publishing your REST services in production, then you should use application mapping name to avoid conflicts and for better management.

To get rid of application name, all you need to do is, make that application as default. There are two ways to do it.
  1. Go to Administrator->REST Services page, edit that application, check the checkbox saying default and update it.
  2. Use below given code if you do not like to go to Admin.
<cfset restInitApplication(absolute_path, mapping_name, "default")>

This will set your application as default and to call your resource you need to hit this URL - "http://localhost:8500/rest/restpath" where restpath is the restpath of your resource.


Few points to remember using default:


Default application is given last preference when you call some resource. Let's say you have a resource with restpath: "one/two" in your default application and you have a resource: "two" in your application named as "one".

  1. So on calling this url: "http://127.0.0.1:8500/rest/one/two", resource with restpath: "two" will be served from application: "one". But if application: "one" is not present then resource "one/two" will be served from default application.
  2. On calling this url: "http://127.0.0.1:8500/rest/one/" (notice a forward slash in the end of url), you will get resource not found, because there is no resource with restpath: "/" in application: "one".
  3. On calling this url: "http://127.0.0.1:8500/rest/one", it will search for resource: "one" in default application because url doesn't has a forward-slash after "one".
There can only be one default application at a time.


Refresh Application:


Once you have registered your application, you might want to change few things in your resources and want to services to reflect the effect. But there is a small hindrance in that. The time you register an application, ColdFusion loads the resources present in that application in memory, so if you are making some changes in you application, you need to tell ColdFusion in some way to refresh the application so that it can reflect the changes.
To achieve this there is a concept of refreshing an application. This can be done in two ways. One is from Administrator-REST Services page you can refresh whichever application you want. But if you want to do it right away from you code, you can use restInitApplication() function.
The same function for registering an application is also used for refreshing an application. If you are calling this function for some application but that application is already registered, then it will refresh it. So the trick is very simple. If application is not registered then restInitApplication() will register it, whereas if it is registered already, then it will refresh it.
For refreshing a default application you need not pass the third attribute("default") but for registering you need to.

Please note that using this function is not recommended in Application.cfc, it might break things. You may use this function in any cfm.



Role of Application.cfc:


If you have Application.cfc in the directory you want to register, then there are few things you might want to know.

  1. this.name - If application name is given in application.cfc, then while registering the application mapping name becomes optional. If you will not give application mapping name then your application will be registered using the name given in application.cfc
  2. this.restsettings.skipcfcwitherror - This is a boolean attribute. Usually if there some compilation error in any of your REST enabled cfc, then while registering you will get an error and you application will not be registered. But if this attribute is true, then even if there are errors in some cfc's, the rest of the cfc's will be published and your application will be registered successfully. Please note that if this attribute is true and all the cfc's have error then error will be thrown that no rest resource found.
  3. this.restsettings.cfclocation - you can give comma separated list of the directory path in this attribute. While registering or refreshing an application ColdFusion will search for all the rest enabled cfc's in these directories too. Please note that in this case, cfc's in current folder will not be considered. If you want to include present directory too, you need to give value something like this: this.restsettings.cfclocation = "/myfolder, ." (notice a dot after myfolder, to include present directory)

Update/Delete an application:

  1. To update already registered application you can go to administrator or you can use same function restInitApplication(). Lets say there is an application with path as "/myfolder" and mapping name as "app1". Now if you call this function: restInitApplication("/myfolder", "app2"), your application registered with "app1" will get updated to "app2".
  2. Though for registration/refreshing/updation same method was used but fortunately there is a separate method for deleting the REST application :) restDeleteApplication(absolute_path). You just need to pass the absolute path of the application registered to delete it.


That will be enough for registering/updating/refreshing the REST applications. I guess so ;)


<- Previous Contents Next ->



Thanks,
Milan.

Tuesday, 21 February 2012

Tutorial on RESTful services in ColdFusion



<- Previous Contents Next ->



Tutorial on REST: Introduction

Much awaited ColdFusion10(Zeus) is out with many new, interesting and challenging features. And REST is one of them. So all the developers out there who wants to switch to REST services from SOAP based web services, get your hands on ColdFusion10 Public Beta now and start with REST right away.

This tutorial is like a roller-coaster ride for REST services in ColdFusion10, which will quickly get you started with simple basics and easy examples and also it will cover all the complex techniques of this feature.


Tutorial on REST: Contents

For now to get you started here are initial few Parts, will be updating more with time.

  1. Part-I : Getting Started
  2. Part-II: Registering a REST application
  3. Part-III: First REST Resource(cfc)



<- Previous Contents Next ->


Thanks,
Milan.

Getting Started with REST in ColdFusion 10



<- Previous Contents Next ->



PART-I

Tutorial on REST: Getting Started:

Background: REST services are a kind of web services which use http protocol behind the scenes. Geeks familiar with SOAP based web services must be thinking, Is this really possible (if they don't already know about REST architecture yet)? Yes, REST services uses HTTP architecture to get the work done and same way ColdFusion10 has beautifully used its component(cfc) to publish the REST services and cfhttp tags to consume them. For more information on REST architecture please go through this link.

Note - for simpler understanding, throughout the tutorial I will consider that ColdFusion is installed at "C:\ColdFusion10\" with webroot at "C:\ColdFusion10\cfusion\wwwroot\" and is running on port "8500".

Publishing
  1. After installing ColdFusion10 and setting the webroot(either through standalone or using webserver like IIS or Apache), first step required to setup REST is write a REST enabled cfc in some folder in webroot.
  2. Create a directory named "restApp" in webroot of ColdFusion. You can name this directory whatever you want to as this is just for your reference.
  3. Create a cfc named as "studentHandler.cfc". You can name this cfc as anything you want. Your REST service users will not use this name untill and unless you are mentioning "restpath" at component level in your cfc. I will come to this point later
Paste code given below in this studentHandler.cfc



For those who prefers to stay independent of Administrator
  1. Just call this function from any cfm.
<cfset restInitApplication("C:\ColdFusion10\cfusion\wwwroot\restApp","IIT")>
  1. First argument to "restInitApplication" function is the absolute path where you have placed your REST component(studentHandler.cfc) and second argument is the name from which you will publish your REST application. You can give your relevant Organization name in second argument.
  2. If you didn't got any error after running this funtion, it means your application is registered successfully. That's it, first REST application published.


For those who prefers to use ColdFusion Administrator page (http://127.0.0.1/8500/CFIDE/administrator/index.cfm)
  1. After saving this file go to Administrator --> REST services page
  2. In Path text box give the absolute path till directory "restApp". In this example it will be "C:\ColdFusion10\cfusion\wwwroot\restApp"
  3. In mapping text box give some logical name for the REST application you going to create, let's say "IIT". You can give your relevant Organization name. This name will be used by users in the URL
  4. Hit register, and there you go. First REST application published.

Behind the scenes/tricks:
(these are quick tricks to know, but will covered in later parts of tutorial)
  1. When you hit 'restInitApplication()' function, ColdFusion registers your application. You can also see that application later on in Administrator REST Services page.
  2. When you create a REST enabled component in your webroot and register that folder, ColdFusion consider that folder as one REST application. 
  3. As many resources(cfc or functions in cfc) as you want, can be created in one application but the only thing is that restpath for these resources should not conflict with each other.
  4. Nested REST applications are not allowed.
  5. You can keep your application outside webroot too. For this you need to add a mapping for a directory in Administrator and then you can register this directory using absolute path or mapping(the name with which you added a mapping), both will work. 
  6. Application names are case-INsensitive.
  7. Calling restInitApplication() for already registered application actually REFRESH that application.
  8. Calling restInitApplication() with different mapping name(second attribute) will update the registered application with absolute path(first argument), with new name.
  9. If you want to skip giving application mapping name, you can use 'default' feature, you can set an application as default and while consuming you can call a resource without giving mapping name in URL. Keep checking  this area for this point. I will write separate post for this.
  10. While registering an application, if application mapping name is not given, then it picks the same in the directory's(one you are trying to register) Application.cfc(this.name).




Consuming


As you saw it was damn easy to publish a REST service but consuming is a lot Easier than that. All you need to do is hit this URL: http://127.0.0.1:8500/rest/IIT/student

I hope you got the response as "foo", because this is what we returned from studentHandler.cfc in function "getMethod".

How URL works:

  1. http://127.0.0.1:8500/ - This is a equivalent to protocol://ip:port of your server in which the REST resource is present.
  2. /rest/ - This string 'rest' in URL is necessary to tell ColdFusion that this is a REST call. You can change this 'rest' in server.xml
  3. /IIT/ - this is the mapping_name from which you registered your REST application.
  4. /student/ - This is the restpath of the resource you defined in studentHandler.cfc
Consuming in cfm:
  1. For consuming REST services in cfm file you need to call the above URL using cfhttp tag.
  2. Run the code given below.
  3. Just take care that the method in cfhttp call should be 'get', as it has to match the 'httpmethod' given in cfc.

How this works
  1. By looking at the URL, ColdFusion gets to know that this is a REST call and it also gets to know that for which application this call has been made because of the mapping name present in URL('IIT' in this example)
  2. Once we know that which application it is, we can easily get to know that which resource(cfc) has been called, because a cfc has a restpath which has to be unique for every appliction and this restpath is also included in URL('student' in this example)
  3. Once we get to know that which cfc has been called, we match the httpmethod of cffunction with the method of the request(cfhttp). In this example for both of them we mentioned 'GET'. So by calling a get request on this resource we hit the function whose httpmethod is 'get'.
  4. Once we know which cffunction to call, its very easy to return the response.
  5. There is also a possibility to have more than one function in same resource with different httpmethod, So it's quite possible that on calling same URL with get request you might hit one function whereas calling 'put' you might hit another. Details about this will be covered later.

Note:Application name(mapping name from which you registered your REST app) is case IN-sensitive.

<- Previous Contents Next ->



Thanks,
Milan.

Friday, 10 February 2012

Equate arrays, structs, query or possible combination of three


Have you ever felt need to compare two arrays in ColdFusion or comparing two structs or may be two queries. If you are reading this, I am sure you felt at some point and if not, you can still read on :)

We use arrays, structs and queries so regularly in ColdFusion that at some point or the other we have to compare them and we dump it to check if its coming fine. Dump is such a powerful tag in ColdFusion that you should use it but what if you want to write a script to check that. Ahhh... cfdump cannot be used there right.

Well not to worry, I have written a code, in fact to be precise I have modified a script (courtesy-cflib.org) which will allow you to compare arrays or structs or queries. Even if you have complex objects like array of struct or array inside struct or query in array of struct or whatever possiblity you can think of these three, you can easily compare using three simple functions: arrayCompare(leftarray, rightarray), structCompare(leftStruct, rightStruct), queryCompare(leftQuery, rightQuery).

I will post complete code n the end, you can save that in .cfm file and call the functions at your will. So it's like if you have two comparable variabes:array of structs, you just need to pass both of them to arrayCompare() OR if you have complex structs having array or query inside you need to call arrayStruct. Handling of array, struct or query present inside your variable will be automatically taken care of.

If both the variables passed by you are equal then this will return a boolean true else false. Find comments inline to understand the code.

So go ahead, you this file, call functions and compare your complex variables at ease.

Click below given link to see the code:



This code is also available at cflib.org but I have modified it according to the need, so it might not be the same. If you are looking for a complete set of three features(array, struct, query compare) this file is perfect for you.

Share if you feel its worth it. Comments will be a +1.

-Milan Chandna

Saturday, 4 February 2012

Continue in cfloop


Have you ever used continue in cfloop without cfcontinue/cfbreak.

Check this code:

Here I have a <cfloop> which runs 10 times for value of 'i'. I want to implement continue tag if the 'i' is an even no. To achieve that check if the no.is even and if it is, I throw a custom error.

The good thing is that you can always catch this error. So Catch this error before closing </cfloop> tag. Though you can add some code over there also but it totally depends on you. For a normal continue you need not add anything in <cfcatch> block. As expected this thrown error wil be caugth in <cfcatch> and it will proceed for next iteration in <cfloop>, without any error. And this is how it behaved as continue.

So all in all you need to remember that

  • instead of continue you can throw a custom error
  • catch this error in the end (before closing </cfloop> tag)
  • Do nothing in <cfcatch> tag (though its your wish but its not necessary)
  • close </cfloop> tag.

Hope you got this.
Cheers!!!

Thursday, 26 January 2012

ColdFusion Chrome theme

Oh Yes, All the ColdFusion lovers who use Chrome Browser for their work or their day to day stuff can now load CF theme from HERE(created by me) into chrome and feel close to CF always. Cheers!!!

Well I will not write much about this as there is already a blog written for it and I will just redirect you ;)


Share, Like and Tweet if you like this.

Milan.

Monday, 3 October 2011

Secured Web Services in ColdFusion


One day I just felt the need to create a Secured ColdFusion Web Service and to my wonder I just found good examples of consuming it but none for publishing it. That influenced me to write a  blog for Web Service published in ColdFusion, consumed in ColdFusion and that too in a secured manner using <cfinvoke>/<cfobject>  username/password feature.

Without giving the overview I will just get into the details but before that it's must to understand that how is ColdFusion behaving from client side . From client side when you give username/password in <cfinvoke> tag or <cfobject> tag (see the sample code below), then ColdFusion sends the information as part of the request. The login information is passed to web server using HTTP basic authentication.



Please note that these are just code snippets. I will share the complete code in the end.



You just saw how easy it is to consume a web service in ColdFusion. Publishing also is a very simple task but there is a twist. ColdFusion doesn't give any specific feature to handle the authentication (username/password) sent by client-side(using cfinvoke/cfobject). But that doesn't mean you can not handle it. ColdFusion has already given an awesome feature of <cflogin> and expects the user to authenticate the credentials using that same feature.

Here is snippet of <cflogin> authentication.



Please read the comments inline to understand the code.

We just saw how to catch the username and password sent in request by cfinvoke but the question is where to use it. I will suggest to use this code in Application.cfc instead of web service component. The reason is, it could save you a lot of code rewriting and easy to maintain. You can just write the code once in Application.cfc in onRequestStart() method and for every request it will ask for authorization otherwise will  send UnAuthorized status.

I hope you got an idea of how to consume a web-service with credentials and how to publish a web-service which gives on access on proper authorization.

So now I will post the complete code for doing this. There will be three files namely: securedws.cfm, securedws.cfc and Application.cfc. I am assuming that ColdFusion9(installed in C:\) is used and these files are kept under C:/coldfusion9/wwwroot/securedwebservices/
Please change the URL of webservices in code given below accordingly if your configuration is different.








Please note that for consuming the web-services always prefer <cfinvoke> tag over <cfobject>. cfobject tag has one limitation, it caches the first username/password and then even if you will change the credentials, it will send the first credentials only.

For example, consider that there are two users for your webservice with two credentials lets say: user1/pass1 and user2/pass2.

First lets use cfobject with credentials of first user(user1/pass1) and try to access the web-service. It will send the correct credentials to web-service. Now change the credentials in the same cfobject and use second user's one(user2/pass2) and access the webservice. This time request should have send second user's credentials(user2/pass2) but it actually passes (user1/pass1). You can confirm this behavior using <cfdump output="console" var="#cflogin#"> at server side.

This behavior is only observed with cfobject only and is quite dangerous. So I will suggest you to use cfinvoke.


Feel free to post any queries.

ColdFusion Rocks!!!

Friday, 30 September 2011

Add Handler to ColdFusion web services



Well first of all lets understand what does adding Handler to ColdFusion web services mean. As the name suggests, you can create and add your class/function in such a way that whenever there is a request/response to ColdFusion soap based web service, your class/function will be called.

Lets understand it from an example.
You created a service in ColdFusion, but you want your program 'Logger' to be called for every request/response so that you can log the service in your own way. Well as the ColdFusion already gives you logging handlers so lets take a good example.

What if you want to digitally sign your soap messages before sending them through ColdFusion. Its easy, I would suggest to use Apache xml security library and write a simple program in Java to do that. But the twist is how to call that java class everytime you send a soap response in ColdFusion. Well there is the need to add the handlers in ColdFusion web service. So here we go trying our hand at it.

Just follow few easy steps.


  1. Create a simple web service in ColdFusion and try to invoke it. See if its working fine and you are getting the expected result. Now open client-config.wsdd kept in {coldfusion_webroot}\WEB-INF\ folder. Take a back-up of this .wsdd and keep it safe. Open this wsdd in notepad and if you will notice, this .wsdd file is in xml format.
  2.  I will give you a snippet of wsdd file which I have modified.

  3. 
     
    
     
      
      
    
      
     
       
      
      
     
    
      
    .
    .
    .
    
    
    

  4. Check out what all has been mofified in this client-config.wsdd file. First of all look for <requestFlow> tag element in this file(usually this will be the child element of <globalConfiguration> element and will be commented by default). If <requestFlow> is commented then remove the comments around it and add this line in between <requestFlow> opening and closing tags: <handler type="myClass"/>
  5. Also notice that there will be one handler already present in it: <handler type="log"/>. This is ColdFusion's handler to log the requests. You can remove this log handler if you do not want your services to be logged(specially in production servers). Just comment this particular handler eg: <!-- <handler type="log"/> -->
  6. After doing this much there just one more line to be added in this wsdd file.  Notice that there is a <deployment> element tag in the beginning of file and its child is <handler> element tag. This handler is provided by ColdFusion for the very same purpose of logging. We will add our handler somewhat similar to ColdFusion's handler: <handler name="myClass" type="java:myClassName"/>. You can add this just beneath handler provided by ColdFusion. 
  7. Save this client-config.wsdd file and we are half way done. Now lets create one sample class for testing this and we will keep its name as myClassName.java, as we have given this very same name in wsdd file. You can choose whatever name you like but make sure to give the same name in handler. You can also make package but you need to keep it in similar manner in wsdd too eg: <handler name="myClass" type="java:myPackageName.myClassName"/>.
  8. Just as I explained the steps to add the handler in <requestFlow> in client-config.wsdd file, similarly you can also add a handler for <responseFlow> so that you can catch the reponses as well.
I will share a very simple code of java which creates one file in local directory so that we can keep a check that this method is getting called everytime web service is hit, by looking at the timetsamp of file created.


//java code
import java.io.*;
import org.apache.axis.handlers.*;
import org.apache.axis.*;

public class myClassName extends BasicHandler
{
 public void init()
 {
  super.init();
  System.out.println("init is called");
 }

 public void createFile() {
  try{
  File f;
  f=new File("D:\\sample.txt");
  if(!f.exists())
  {
   f.createNewFile();
   //New file has been created to the specified directory
  }
  }catch(IOException e)
  {e.printStackTrace();}
 }

 public void invoke(MessageContext mCtx) throws AxisFault {
  try {
   this.createFile();
  } 
  catch (Exception e) {
   e.printStackTrace();
  }
 }

}
Compile this program and keep the class file in {ColdFusion_documentroot}\lib\
Usually it will be C:\ColdFusion9\lib\

Understanding myClassname.java
  1. First of all I have imported few axis classes which are required for handler
  2. I have also extended the class with BasicHandler class of axis. This class is present in org.apache.xml.handlers.* in axis.jar (found in {ColdFusion_documentroot}\lib folder)
  3. This BasicHandler is an abstract class with invoke(MessageContext) as abstract method which is why its necessary to implement this method. This method throws AxisFault Exception. You can use this method for whatever you have to implement, 
  4. Other than this we have also written init() method. This method will be called first time when your handler(myClassName) will be called.
  5. You can extend this program's functionality to whatever you want.


Well that is it.
Just restart the server(as we have added myClassname.class in lib folder) and access the web service created by you, you will see the file created successfully. 


This way you can add whatever handler you want and as ColdFusion web services are based on Axis, you can take strong benefits of Axis library and do whatever you want with your web services in ColdFusion.


Feel free to post any queries.

ColdFusion Rocks!!!