Using ColdFusion APIM To Import API From Swagger

As discussed in previous blog there are 5 ways of creating APIs in ColdFusion API Manager. We have already seen How To Create Manual API In ColdFusion API ManagerNow we will import an API from Swagger. 

Swagger is a specification for describing, producing, consuming, and visualizing RESTful web services. APIM supports Swagger 1.2 as well as 2.0.

Read more here : Using ColdFsion APIM to import API from Swagger

 

How To Create Manual API In ColdFusion API Manager

ColdFusion API Manager helps you to create APIs that expose core functionalities of application and other backend systems. These APIs are then published and managed at runtime.

We can create APIs in multiple ways :

  1. Creating API Manually
  2. Importing API from Swagger
  3. Importing API from ColdFusion REST services
  4. Converting a SOAP service into a REST service
  5. Import a SOAP API through a proxy service
In the series of blogs to follow we will cover each flow. In this blog we will cover manual creation flow.
 
 
 

Creating a simple facebook app which manipulates your profile pic

In CF10 we had introduced cfoauth tag which helped in social login integration. Lets use it to build a simple facebook app which will download your facebook profile’s pic, add some image effects to it and post it to facebook.

1. First we need to ask user to login via facebook so that we can fetch his profile image.

<cfoauth type=”facebook” clientid=’YOUR_CLIENT_ID’   secretkey=”YOUR_SECRET_KEY_HERE”  result=”r” scope=”” redirecturi=”REDIRECT_URL”>

 

2. Not lets set this info into some variable 

<cfset Session.fbinfo = #r#>

 

3. Use cfhttp tag to download the image

<cfset thisPath=ExpandPath(“*.*”)>

<cfset thisDirectory=GetDirectoryFromPath(thisPath)>

<cfhttp method=”Get” url=”http://graph.facebook.com/#Session.fbinfo.id#/picture?type=large” path=”#thisDirectory#” file=”final.jpg”>

 

4. Now lets use cfimage tage to do various image manipulations 

<cfimage action=’resize’ height=’#height#’ width=’#width#’ source=’#thisDirectory#/final.jpg’ destination=’#thisDirectory#/final.jpg’ overwrite=true> 

<cfimage action=’rotate’ angle=’#angle#’ source=’#thisDirectory#/final.jpg’ destination=’#thisDirectory#/final.jpg’ overwrite=true> 

<cfimage action=’border’ thickness=’#thick#’ color=’#color#’ source=’#thisDirectory#/final.jpg’ destination=’#thisDirectory#/final.jpg’ overwrite=true> 

5. Save the image 
<cfimage source=”#image#” action=”write” destination=”#thisDirectory#/final.jpg” overwrite=”yes”>
6. Lastly post this image to Facebook 

<cfhttp  url=”https://graph.facebook.com/me/photos?access_token=#Session.fbinfo.access_token#” method=”post” multipart=”yes”>
   <cfhttpparam type=”file” name=”source” file=”#thisDirectory#final.jpg”>
</cfhttp>

 

 

Cfgrid JS binding issue is fixed in Coldfusion 11 update 3

Coldfusion 11 update 3 fixed the cfgrid javascript binding issue.(bug number 3712909,3712885)

Prior to this, js binding was broken where as CFC binding as well as URL binding were wroking properly.

As a result pagination, dynamic binding etc were not working if js binding was used though basic static grid was working properly.

Even query columns were not getting mapped to their associated grid columns.

This had happened due to our internal upgrade of EXTJS framework which did not support js binding.

So we had to write a custom js binding wrapper to make it work in coldfusion. Now everything works fine in JS binding

Enabling Leading Wildcard Search In Coldfusion

In the current version of Solr supported by Coldfusion, leading wildcard search is not supported by default. A ’*’ as the leading character in a search will not work. 

For example this code :

<cfsearch collection=”new” name=”x” criteria=”*title*” categorytree=”books/history/english”>

Will throw an error :

There was a problem while attempting to perform a search.

Error executing query : org.apache.lucene.queryParser.ParseException: Cannot parse ‘*title*’: ‘*’ or ‘?’ not allowed as first character in WildcardQuery

 

Workaround for this is to tweak schema.xm of the collection and add ReversedWildcardFilterFactory  filter.

To enable “*criteria*” kinda search go to schema.xml file of the corresponding collection and add this filter to fieldtype with name “text”

<filter class=”solr.ReversedWildcardFilterFactory” withOriginal=”true”

             maxPosAsterisk=”2″ maxPosQuestion=”1″ minTrailing=”2″ maxFractionAsterisk=”0″/>

And restart you solr.

But do remember that Using ReversedWildcardFilterFactory will double the size of your dictionary (more or less), maybe drop in performance. So use it only if it is really required by your application

 

Workaround for ajax cfgrid bug in CF11 in which ajaxonload() is not working properly

In coldfusion 11 release there is an open bug in which if you try to use any ColdFusion.grid related function in a function that is called by ajaxOnLoad, the grid object will not be available. 

A grid will load properly, but when the javascript function is called with AjaxOnLoad and  function tries to reference the grid, you will get that the reference is “undefined”.

This is a sample code :

<html> 

   <head> 

      <title>AjaxOnLoad test</title> 

        <script> 

            init = function() 

            { 

                ColdFusion.Grid.sort(‘datagrid’, ‘col_one’, ‘ASC’);

            } 

        </script> 

    </head> 

 <body> 

        <cfform name=’formOne’>

            <cfgrid name=’datagrid’ format=”html” textcolor=”blue”>

                <cfgridcolumn name=’col_one’>

                <cfgridrow data=”data1″>

                <cfgridrow data=”data2″>

                <cfgridrow data=”data3″>

            </cfgrid>

        </cfform>

        <cfset AjaxOnLoad(“init”)> 

    </body> 

</html>

The above code will break at “ColdFusion.Grid.sort(‘datagrid’, ‘col_one’, ‘ASC’);” as grid object will not be available at that moment.

 

Workaround :

The current workaround for this issue is to wrap the references to the grid objects within Ext.onReady method, like this:

   init = function() 

            {

   Ext.onReady(function ()

                {

                                 ColdFusion.Grid.sort(‘datagrid’, ‘col_one’, ‘ASC’);

});

            } 

 

Note: Fix for this bug will be available in next update

Specifying datatypes in Spreadsheets

We have often encountered bugs around datatype of data being written in spreadsheets. For example string like 8E45000 getting converted into a floating type or a string like 4D or 4F getting converted to numeric etc.

The internal logic used to extract the data type of the data sometimes isnt that accurate and we would end up in writing corrupted data in spreadsheets.

With Splendor now we provide users with the option of specifying the datatype of the data being written in spreadsheets. In this way we can avoid the internal logic of determining the datatype which sometimes used to corrupt the data.

This option will be supported in these 3 mehotds : SpreadSheetAddRow,SpreadSheetAddRows,SpreadSheetSetCellValue

Possible datatype of a cell can be : STRING, NUMERIC or DATE

Here is the syntax :

SpreadSheetAddRow( ExcelInfo excelvar, String value, int row, int column, boolean insert,String datatype )

where ‘datatype’ is an expression which describes the datatype of data.

Here are examples :

STRING:1,3;NUMERIC:2 –> Data in 1st and 3rd column of this row will be of type string, and that of 2nd column of type numeric

NUMERIC:1;STRING –> Data in 1st column of this row will be of type numeric, rest all will be of type string

NUMERIC:2-5;STRING:1,6;DATE –> Data in 1st and 6th column of this row will be of type string and data from 2nd to 5th column will be numeric and rest of type date.

STRING –> All cells in this row will be of type string

string;numeric:3,4 –> This is an invalid expression. Only last in the sequence can skip mentioning column numbers. In that case we will assume rest all columns will be of that datatype. For example this will work :NUMERIC:3,4;STRING

If for any cell datatype is not specified, it will fallback to old way of extracting the datatype.

Similarly we take datatype attribute in other methods also :

SpreadSheetAddRows( ExcelInfo excelvar, Object q, int startrow, int startcolumn, boolean insert,Object datatypes )

Where ‘datatypes’ will be an array of datatype expressions

SpreadSheetSetCellValue( ExcelInfo excelvar, String value, int row, int column, String datatype )

Where ‘datatype’ is datatype of the cell

 

SpreadSheetAddPagebreaks and SpreadSheetAddAutofilter

We have added 2 new methods in spreadsheet.

1.SpreadSheetAddPagebreaks 

Spreadsheets can have pagebreaks which breaks sheets into multiple regions when you want to print it. You can put these line breaks along rows as well as columns.

Here is the syntax :

SpreadSheetAddPagebreaks( ExcelInfo info, String rowbreaks,String colbreaks )

where info is the ExcelInfo object, rowbreaks are the row numbers and colbreaks are the column numbers where you want to put the page breaks.

For example, SpreadSheetAddPagebreaks(info,”,’2′) breaks the sheet into two parts with columns A,B,C in the first and D,E,… in the second. Similarly, SpreadSheetAddPagebreaks(info,’2′,”) breaks the sheet into two parts with first three rows (rownum=1…3) in the first part and rows starting with rownum=4 in the second.

Here is another example :

SpreadSheetAddPagebreaks(  info, ‘1,2’,’3,5′ )

This will put page breaks on rows 1 and 2 and columns 3 and 5. So if this sheet is send for print it will have multiple regions to be printed.

 

2.SpreadSheetAddAutofilter 

This method helps in enabling filtering for a range of cells. Filtering data is a quick and easy way to find and work with a subset of data in a range of cells or table. For example, you can filter to see only the values that you specify, filter to see the top or bottom values, or filter to quickly see duplicate values.

Here is the syntax :

SpreadSheetAddAutofilter ( ExcelInfo info, String autofilter )

where info is the ExcelInfo object, autofilter is the cell range

Here is example :

SpreadSheetAddAutofilter (  info, ‘A1:C2’)

This will apply autofilter on the sheet for the cell renage A1 to C2

Performance improvements in SpreadSheet

There has been considerable improvements in spreadsheet performance. We have done alot of internal code changes to improve this performance. Apart from internal changes we have also exposed something for users.

SpreadSheetWrite method and write action of cfspreadsheet tag now takes one more parameter ‘autosize’.

By default now all the excel sheets have all their columns expanded and resized once they are written. Column expansion is a very expensive process which if avoided can save some valuable milliseconds.

Here is the syntax :

SpreadSheetWrite( ExcelInfo info, String filename, String password, boolean overWrite,Object autosize )

Autosize can be a boolean or an array

–> If it is boolean, true means expand/resize all the columns and false means do not expand/resize any column.

SpreadSheetWrite( info,filename,password, true,false )

–> If it is an array, it should be array of columnn numbers which you want to expand. 

<cfset arr= [1,2]>

<cfspreadsheet  action=”write” filename = “test1.xlsx” name=”store” autosize = “#arr#” overwrite=true>

 

By default value will be true for backward compatibility. We recommend users to keep it false

Improvements and Enhancements in SpreadSheet

In the coming release we have made few updates in spreadsheet :

1. Overall performance has improved a lot. Read/write/update/format operations should be faster and consume less memory

2.  SpreadSheetWrite method now takes ’autosize’ parameter. If it is false, columns of output spread sheets wont be resized and users can avoid this expensive operation

3. New methods like SpreadSheetAddPagebreaks(adds page breaks in spreadsheet) and SpreadSheetAddAutofilter(Sets autofilter on the specific sheet) have been added

4. Internally POI has also been upgraded to 3.9 version

5. SpreadSheetAddRow/SpreadSheetAddRows/etc methods also take ’datatype’ attribute now where user can specify the datatype of data being added. In this case CF will not use default way of extracting the datatype of data being added (which sometimes lead to inconsistent behavior).

6. Tons of bugs have been fixed in this area

I will be writing in details about each point in next blog posts