Showing posts with label ColdFusion. Show all posts
Showing posts with label ColdFusion. Show all posts

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