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.