Strange behaviour component, methods not found
I have a really really strange bug. All my applications have a settings.cfc in the webroot of the application. Some cfc's have more methods than others but all my other cfc's extend the root settings.cfc, all cfc's are stored in an application variable called application.cfc and all applications have their own application_name (in case you are wondering)
The bug i'm having is that the correct settings.cfc is extended but a certain method in that cfc is not found..... if I remove all methods it keeps finding the other methods???, but if I change the this variables with other values in the settings.cfc it will see those changes???
It appears to me that the application scope is saving or caching a different settings.cfc and his methods instead of the correct one. Especially because if I remove the methods it will still show the methods in a cfdump....
Could anyone point me in the right direction??
4344 viewed | 3 opinion(s) | Tjarko @ 21:25 cet
s3 REST wrapper with ACL and storage choice
Based on the wonderful wrapper that Joe Danziger
build about a year ago and the update that Steve Hicks
made, I made the wrapper with extra storage choice. You can now choose if you want your bucket stored on the US data storage or in my case the European data storage. Download the new and improved s3 REST wrapper
The modified code now takes into account the ACL and the STORAGE:
* putBucket(bucketName, acl, storage) - create a new bucket with the defined ACL and storage.
I have also modified the S3test.cfm so that it includes a drop down for the storage choice US or EU.
The s3.cfc now also takes into account the 307 redirect "error" you get when using EU storage. All the methods have changed to work with the "new-style" REST API and the 307 redirect. The 2 functions that get this "error" are deleteBucket and putObject, i haven't tested the deleteObject code but if this doesn't work just copy/paste the 307 bit from the other methods.
Enjoy!! And if someone could improve the code that would be even better!! This was a quick fix and it could probably improve here en there :-)UPDATE
: I forgot to mention that I don't use the getObject method to get my files... so that method is not working in this exampel. I use the host mybucket.s3.amazonaws.com/filelocation way of getting to the file.
6097 viewed | 3 opinion(s) | Tjarko @ 12:04 cet
Reading Excel 95 files with Coldfusion, part I
First of all, let me introduce myself since I hadn't done so in my first post
Hi, I'm Jax, a friend of Tjarko, and I have been a Coldfusion user for the last decade or so. I am also a fairly experienced Java programmer.
I am currently working on a project that involves a bit of data harvesting from various sources.
One of the data sources is an Excel file hosted on ( or actually: generated by) another webserver. So I needed something that could read and parse a true Excel file (so not a csv file with an xls extension). It would be nice if it could also use the Excel file straight from the web as it's source, without me having to locally save the file first.
Coldfusion installs with a version of the POI libraries
which can handle all this just fine. And to top it off Ben Nadel wrote a utility component
that interfaces this library.
"Great !' I thought, 'Someone else already did all the dirty work (Thanks Ben!), and all I have to do is write a few coldfusion lines and I'm off!'. A good thing, because data harvesting is only a small part of the the project I'm working on and I had other, bigger fish to fry.
I started testing with his component but I couldn't succesfully parse any of my Excel files. As it turned out POI does not support Excel '95 (or older) files. And my datasources where all, you guessed it, Excel '95 files.
So... back to the drawing board it was. I did some research and came across the JExcelApi
which could handle Excel '95 files.
Hence, the JExcelApiUtility.cfc was born.
<cfcomponent displayname="JExcelApiUtility" output="false" hint="Utility class, interfacing the JExcelApi. Reads Excel files.">
// START: access through setters and getters
variables.workBookLoaded = false;
variables.workBook = "";
// END: access through setters and getters
<cffunction name="init" access="public" output="false" returntype="JExcelApiUtility" hint="Constructor">
<cfset variables.workBook = createObject("java","jxl.Workbook")> <!--- default constructor will suffice --->
<cfthrow message="Could not create Instance of JExcelApi (jxl.WorkBook): #cfcatch.detail#" >
<cffunction name="loadWorkBook" access="public" returntype="void" output="false" hint="Reads an Excel file.">
<cfargument name="excelFile" type="any" required="true" hint="path to excel">
<cfset var aFile = "">
<cfset variables.workBook = "" >
<cfset aFile = createObject("java","java.io.File").init(arguments.excelFile)>
<cfset variables.workbook = variables.workbook.getWorkBook(aFile)>
<cfthrow message="Could not load workbook with arguments: #arguments.excelFile#, detail: #cfcatch.detail#" >
<cffunction name="isWorkBookLoaded" access="public" output="false" returntype="boolean">
<cffunction name="setWorkBookLoaded" access="private" output="false" returntype="void">
<cfargument name="workBookLoaded" required="true" type="boolean">
<cfset variables.workBookLoaded = arguments.workBookLoaded>
- Allthough the above code works, it is far from complete. The next parts in this series will feature a more usuable version, so stay tuned.
- Working with this component requires you to have the jxl.jar installed in coldfusion's classpath. You can find the jar sitting in the zip download available from JExcelApi.sourceforge.net.
There are a few things worth noting here.I created a setter and getter method ( in this case, the getter method is more of a convenience type) that will only tell us if the JExcelApiUtility object
holds a workbook or not. It's use will become more obvious in the next parts.
<cfset aFile = createObject("java","java.io.File").init(arguments.excelFile)>I created an instance of java.io.File that is instantiated with the path to the Excel file. This instance ('aFile') will create a File object that the jxl.workbook instance can use to, in turn, return a workbook object. We can't simply feed jxl.workbook the path, because the path is an object of type String and jxl.workbook can't convert a string into a workbook. And while we are at it, you also can't initiate jxl.workbook with a cfhttp.filecontent either, because cfhttp.filecontent is of type java.io.ByteArrayOutputStream.
<cfset variables.workbook = variables.workbook.getWorkBook(aFile)>
It will however accept an inputStream and that is what I will discuss in part II.
9346 viewed | Your opinion... | Jax @ 16:06 cet
New version CFCDoc: CFCDoc revamped
You might have heard of CFCDoc. A tool that creates Javadoc-like documentation from your CFC's .
A week or so ago I came across the original CFCDoc again, because a colleague was in need of something like it.I decided that CFCDoc could do with a bit of revitalising, so I went ahead and changed things around a bit.
Hence CFCDoc revamped
I have released it under de Common Public License again and you can find it at cfcdoc.riaforge.org
, so go and check it out!
6622 viewed | 5 opinion(s) | Jax @ 9:43 cet
Getting country by IP based on GeoLite
For a global application I needed some way to determine the country of the visitor. A couple of years ago I used a similar solution but that database was not available anymore. The guys at Maxmind however publish a free, yes free geoIP database
every month and according to them it has an accuracy of 98% procent.
So what I did was rewrite my original component so now it is speaking to this new database from Maxmind. Here are the steps to make this work for you!
First download the geoIP Lite datbase from Maxmind
. (CSV format)
Import this into your favorite database, mine is MSSQL. Maxmind has different links to examples on how to do this.
Name the table "geoip" and the columns "begin_ip,end_ip,begin_num,end_num,country,name", and make sure that if you are using MSSQL that the _num columns are of datatype BIGINT.
After that copy/paste the following component and save this as geoip.cfc
<cffunction name="ip2country" access="remote" returntype="query">
<cfargument name="ip" required="yes" type="string">
<cfset var q = "">
<cfset Aip = ListToArray(arguments.ip,'.')>
<cfset Aip = ((Aip * 16777216) + (Aip * 65536) + (Aip * 256) + (Aip))>
<cfquery name="q" datasource="-- YOUR DSN ---">
WHERE begin_num <= <cfqueryparam cfsqltype="CF_SQL_BIGINT" value="#Aip#">
AND end_num >= <cfqueryparam cfsqltype="CF_SQL_BIGINT" value="#Aip#">
After that make a test page with this code in it. If all goes well it should display the country that your are currently in.
<cfinvoke component="geoip" method="ip2country" returnvariable="qCountry">
<cfinvokeargument name="ip" value="#cgi.remote_addr#" />
To make it a bit easier to import this database I have made a download available
for you guys and gals in a normal TXT format. A what the heck.. the complete code is in the download.
9656 viewed | 3 opinion(s) | Tjarko @ 11:01 cet
Components, root, extends and how to tackle it.
Slash, Dot... and what's up with that Coldfusion root!!
When using components in Coldfusion you have probably run into the following problem.
For invoking or creating the object you need to pass an absolute path to the component, and
the absolute path is normally the path calculated from the root of your ColdFusion installation.
In my case: "c:\inetpub\wwwroot\"
So what's the problem then?? Well... because ColdFusion will calculate the path from the root and
no self-respecting hosting provider will have it's websites placed in the root... how do we access
the component then? With a mapping? Yes.. that's one way (the other is explained later) and probably
the only way, if you don't have control over your ColdFusion administrator. A mapping is a "logical" name for a certain directory path
on your server. For instance: my website runs in the "c\inetpub\websites\mximize\" directory and
a mapping "mximize" is pointing to this directory, i can now invoke a component
that is in the "cfc" directory of my application in thefollowing manner.
<cfinvoke component="mximize.cfc.mycomponent" method="mymethod" />
Problem with this is that you "hardcode" the mapping.. and we don't want that... oh wait a minute..
I don't want that!! Normally I create an application var for this that's in my "settings" variables.
<cfset applicaton.settings.mapping = "mximize">
This way I can invoke the component with a dynamic name, so when I switch from test/staging to a production
machine and the mapping name is different, I only have to change application variable.
<cfinvoke component="#application.settings.mapping#.cfc.mycomponent" method="mymethod" />
There is however a problem with this method of coding! When you use the extends attribute of a
component you CAN'T use a variable name for it :-( so with an extend you still have to hardcode the mapping
into your component, and I use the extends attribute a lot!!
<cfcomponent extends="mximize.includes.settings" />
So what would be the most ideal solution then? The most ideal situation is, if you can delete the
following mapping from your ColdFusion administrator's mappings.. "/" pointing to the "c:\inetpub\wwwroot" directory.
This mapping is the one that is responsible for having to code in the above way.. and that's a pain in the.. uh.. behind.
What happens when you delete this mapping, is that ColdFusion will magically see your website as his root!! You can now code
from the same rootpath that you probably code your images / stylesheets etc.. from. So it's no longer a mapping but just simply
calculate from the root of the site.. NOT the root of where ColdFusion was installed. An invoke and a extend would look like this.
<cfinvoke component="cfc.mycomponent" method="mymethod" />
<cfcomponent extends="includes.settings" />
Much much easier, and no mapping needed.
9634 viewed | 1 opinion(s) | Tjarko @ 8:40 cet