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:
YYYY-MM-DDTHH:mm:ss.sssZ
To return a date in ISO format, you can use the toISOString.

If a date string is not in the ISO format, JavaScript uses the following rules to parse it.
Short dates
  • The format must follow the month/day/year order, for example "06/08/2010".
  • Either "/" or "-" can be used as a separator.
Long dates
  • The year, month, and day can be in any order. "June 8 2010" and "2010 June 8" are both valid.
  • The year can have two or four digits. If the year has only two digits, it must be at least 70.
  • Month and day names must have at least two characters. Two character names that are not unique are resolved to the last matching name. For example, "Ju" specifies July, not June.
  • A day of the week is ignored if it is inconsistent with the rest of the supplied date. For example, "Tuesday November 9 1996" resolves to "Friday November 9 1996" because Friday is the correct day of the week for that date.
Times
  • Hours, minutes, and seconds are separated by colons. However, some of the parts can be omitted. The following are valid: "10:", "10:11", and "10:11:12".
  • If PM is specified and the specified hour is at least 13, NaN is returned. For example, "23:15 PM" returns NaN.
General
  • A string that contains an invalid date returns NaN. For example, a string that contains two years or two months returns NaN.
  • JavaScript supports all standard time zones, and Universal Coordinated Time (UTC) and Greenwich Mean Time (GMT). (The ISO format does not support time zones.)
  • Text enclosed in parentheses is treated as a comment. The parentheses can be nested.
  • Commas and spaces are treated as delimiters. Multiple delimiters are permitted.

You may find this link useful - ECMA script date time string format


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:
  1. Server level
  2. Application level
  3. Component level

Publishing

  1. Server level: In ColdFusion 10 WebServices administrator page there is a new setting called as wsversion. This setting defines the default version of Axis that will be used to publish the WebServices in ColdFusion if you have not specified it at Application/Component level.

    Default value of this setting is set to '2', which means by default your WebServices will be published using Axis-2. You can anytime change it to '1' if you are facing the problems.

    This will be very handy if you are consuming all your WebServices from ColdFusion 9. In ColdFusion 9 Axis-2 is not supported and hence your WebServices will be consume by Axis-1 only, so that is why if all your WebServices are consumed in ColdFusion 9 then you can set this to default '1' for whole server.
  2. Application level: In Application.cfc you can specify an attribute as this:

    <cfset this.wssettings.version.publish = "2">

    Setting this attribute at Application level will ensure that all WebServices in this Application will be published using this version of Axis if not overridden at component level.
  3. Component level: In you WebService component (mywebservice.cfc) you can specify this attribute as this:

    <cfcomponent wsversion="1">Specifying this attribute will ensure that this WebService will be published using Axis-1

Consuming

ColdFusion understands that WebServices could be published from any platform and can be consumed from CF so to make it easy CF automatically detects if the service is published in Axis-2 or Axis-1. If it's published in Axis-2, CF will consume it using Axis-2 unless overridden and same goes for Axis-1 too.

You can however override this behavior if you are very sure of the published verison, at two levels:
  1. Application level: In Application.cfc you can specify an attribute as this:

    <cfset this.wssettings.version.consume = "2">Setting this attribute at Application level will ensure that all WebServices in this Application will be consumed using this version of Axis if not overridden at component level.
  2. Invoking level: While invoking the WebService you can specify an attribute 'wsversion' to tell CF from which version the Service should be consumed.

    ws=createObject("webservice","http://localhost:8500/mycfc.cfc?wsdl",{wsversion="2"})
    <cfinvoke webservice = "http://localhost:8500/mycfc.cfc?wsdl" method="echo" wsversion="2" returnVariable="foo" >


I am sure that if you read this post, you will never stuck in Axis-1/Axis-2 compatibility issues.
Specially it is a must for any user who is publishing WebService as in ColdFusion 10 but consuming them in ColdFusion 9 or earlier releases. It's because in CF 10 by default Axis-2 will be used whereas in earlier CF releases only Axis-1 was supported, so you might run into issues if will not take measures.

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
  1. SOAP 1.2 support (SOAP 1.1 was there with Axis-1) 
  2. WSDL2 support
  3. Wrapped styled WSDL support
  4. Easy switching from Axis-2 to Axis-1 and vice-versa.


Taking these points one by one.
 
  1. SOAP 1.2 support - SOAP is a standard protocol specification for exchanging messages and 1.2 is it's latest version. Being a ColdFusion user you should not worry about the implementation part but you should know that now you can consume much wider range of WebServices and also publish for a much wider userbase.
  2. WSDL2 support - WSDL is a standard XML format to expose your WebServices to outer World. Versoin 2 is the latest version of WSDL and now with ColdFusion 10 you can leverage it. Implementation is as expected way too simple.
    The WebService WSDL links are like these : http://myip/mywebservice.cfc?wsdl

    The WebService WSDL2 links are like these : http://myip/mywebservice.cfc?wsdl2
    Now to consume these WebServices using WSDL2 format just update the WSDL link by appending a numeric '2' in the end and you will be done. No change required from publishing side.
  3. Wrapped styled WSDL - A user who has already used WebServices in any platform might be aware of terms like RPC style, Document-literal, Document-wrapped style WSDL. WSDL publishing formats could be in either of these widely used formats. Earlier RPC and Document-literal styles were supported but now Document-wrapped style is also supported.To use this a style attribute is provided at two level: Application level and Component level.
    1. Application level:
      <cfset this.wssettings.style = "Wrapped | Document | RPC">
    2. Component level:
      <cfcomponent wsversion="2" style="Document | Wrapped | RPC" >
      For in-depth details about new attributes in ColdFusion 10 WebServices read this blog here.
     
  4.  Easy Switching - Axis-1 and Axis-2 has few compatibility issues because of their architecture which means if you are publishing in Axis-1, it has to be consumed by Axis-1 only and if a WebService is published in Axis-2 then it has to be consumed using Axis-2 only. ColdFusion is well aware that the users could face problem because of this behavior. So to it make very easy for users, ColdFusion 10 has taken few steps which are discussed in detail in this blog here.



    You may also like reading this -> http://www.adobe.com/devnet/coldfusion/articles/axis2-web-services.html

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.

/*---code starts---*/
function handlepdf(data) {
 
var http = require('http');
var fs = require('fs');

var options = {
  host: CFip,
  port: CFport,
  path: '/rest/services/pdf',
  method: 'POST',
  headers: {
   'Accept': 'text/xml'
  }
 };
 
 var req = http.request(options, function(res) {
  var allchunk = "";

  res.setEncoding('utf8');
  
  res.on('data', function (chunk) {
   allchunk += chunk;
  });
  
  res.on('end', function () {
   var file = allchunk;
    
   fs.writeFile( 'sample.pdf', allchunk, 'base64', function(err) {
    if(err) {
     console.log(err);
     } else {
     console.log("The file was saved!");
    }
   });
  });
 });
 
 req.write(data);
 req.end();
}
/*---code ends--*/
..

Now lets understand the code:

I have written a function handlepdf(data), which accepts the html document as an argument. You can call this function as a callback handler for any event you like.

In this function I am making a http call to ColdFusion server because finally http request is all required for REST to work. I am setting the options of this request to match the CFC I created in my previous blog here

  1. method - post
  2. ip - CF server ip
  3. port - CF server port
  4. path - rest/services/pdf
  5. accept header - "text/xml"
Now moving ahead there is another function which will be called when this http.request will be ready.
In this function I am initializing a variable "allchunk", this is the variable where our complete pdf will be saved.
And on res.on('data'), I have called another function. This function will be called whenever data will be received on response of this request. Inside this function I am appending all the data to 'allchunk'.

One more way to do this was I could have taken allchunk in res.on('data') function itself but the limitation with that approach is that sometimes if the file is big then the response comes in small chunks several times. So using the above used approach will give you complete file.

Once I recieved complete file then on res.on('end'), I am writing this file from server itself, you can however pass to any client. For writing this file I am using filesystem package and writing it with encoding base64. Please take care of the encodings used while calling http request and saving the file otherwise your file could be corrupt.

In the end I am writing the html data in request and closing it, which will call function we have discussed above.

And extremely sorry for incomplete code of node.js but I just wanted to focus on calling ColdFusion part.

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 ->