SerializeJSON() and ORM watch out!

I'm not sure if this is a bug or the way ColdFusion 9.0.1 works, but today I had an issue with the way ColdFusion was serialising an ORM Entity.

I was making a simply AJAX call and in CF using serialiseJSON() method on an ORM object. My issue was that any object that had a property that was an array of other objects was not being returned.

I posted the issue on stackoverflow but then I remembered having the same issue in a Google Group Post on Taffy. I remember resolving this at the time by splitting up the object and basically recreating it again. I was about to do the same thing then on the Adobe livedocs and spotted "remotingFetch"

Quote: "If remotingFetch is false, then the value of that attribute is not sent over flash remoting. The attribute is true by default for all properties. However, for ORM CFCs where persistent = true, the value of the remotingFetch attribute is set to false, by default, for one-to-one, one-to-many, many-to-one, or many-to-many relationships. After enabling this on my relationship it fixed the issue! However as this was referred to under "flash remoting." I missed it the first time around."

After enabling this on my relationship it fixed the issue! As this was referred to under "flash remoting." I missed it the first time around. Just something to watch out for.

Sep27

API Authentication with Taffy

Recently I have been working with Taffy to create a simply REST API. The API is used by a native mobile application on the iPhone. When it was complete I needed a simply way to authentication the application talking to the API.

This is not something I was familiar with at all. I looked into lots of different methods before I started. I really did not want, nor have the experience to reinvent the wheel, so I look at current methodologies around the web.

My first attempt was BASIC authentication, but this did not feel right. For reasons I won't go into here, the API was not over HTTPS, anyone could sniff out the password. Bad, very bad!

I found a really good post by Greg Moser on AJAX Authentication with Taffy REST API. He talks about using sessions as an API key. This is a good idea, but as my application is mobile, not really applicable for my situation. However his post did get me thinking and was very helpful.

I didn't need the complexity of OAuth. I found that I liked the way Amazon secures their API. So I looked more into this approach.

I needed a simple "half OAuth" approach. Mainly without the user having to approve. This is how I got my head around it all and what I ended up with, code and explanation below.

Continue Reading

Sep22

CFMAP: address not valid error message solved

After some minor frustration today with CFMAP and the way it sends addresses to a geocoding service, I am now back on track. I just wanted to write a quick post for anyone else that may run into the same issue. CFMAP was leading me down the wrong path, telling me a bunch of addresses were invalid - "not found". When I directly used the geocoding functionality from Google to test the addresses i.e.

view plain print about
1"http://maps.google.com/maps/geo?q=#address#&output=csv&sensor=false&ke y#yourgooglekey#
2200,5,52.6006027,-1.1840779

Google returned "ok" status code, including the longitude and latitude details I needed. The addresses was indeed valid as far as Google was concerned. So something else was afoot.

Next, I tried the longitude and latitude values in CFMAP and excluded address attribute. This time however all my 50 markers were loaded correctly with no errors.

I looked at the Google Maps API in more detail. I found they had implemented a geolocation service that takes the address you've supplied, and then converts it to longitude etc. As it turns out this geolocation service restricts the total number of requests, per second you can make. It seems CFMAP uses this same geolocation service when you don't have longitude or latitude in your map item tag.

Looking at my own source, ColdFusion makes all the requests to this service in just one call. After the confusing error message, I was beginning to think this was my issue and not that the addresses were invalid.

Anyhow, a quick Google, and Jedi Master to the rescue! Easy when you know what to search for, right?

Ray resolved this issue by calling a CFC to get the lat and lon points, then sleeping for 500ms before continuing in the loop, he saves the results into the application scope and then keep looping, checking if it exists until he has them all in this app scope.

I decided to use this solution, but in a different way. I did not want to use the application scope because my data changes to often.

So I change my approach. I created two new fields in my database for both longitude and latitude. When my users creates a new "address" via my backend, I create the Google Geocoder V3 CFC. And then save the results to a database. As my users add events one at a time, I would not run into the restriction here... Well, I could, but it's very unlikely, right?

view plain print about
1// Geo Get Funtions
2local.geo = createObject("component", "eventManagerApp.com.utility.googlegeocoder3");
3local.geoResults = geo.googlegeocoder3(address="#rc.venueDetails.getvenueAddressLine1()# & #rc.venueDetails.getvenuePostCode()#");
4// Save Geo Function
5rc.venueDetails.setvenueLon(local.geoResults.longitude);
6rc.venueDetails.setvenueLat(local.geoResults.latitude);
7rc.venueDetails.setvenueAddressType(local.geoResults.result_type);
8// Save
9rc.venueDetails = geteventVenueService().save(entity=rc.venueDetails);

I could now use the raw longitude and latitude data without calling the geo service by using the address attribute and incurring the per second restrictions.

I loaded over 50 markers without any issues! Thank You... O, and what a run around!

Apr14

Mura FW/1 and ValidateThis Plugin

I had a few hours today which I set aside to learn more about FW/1 and ValidateThis. I wanted to use both of these frameworks within a Mura Plug-in I had created. I have never used ValidateThis, so I wondered how hard it would be to add it into the fw/1 Plug-in. I am not saying below is the best way, it's my first attempt and I welcome ideas :)

Continue Reading

Jan31

Setting up Security Roles in ColdBox

Fake Jake is back. He wants to secure some of his events based on 'roles' within ColdBox. ColdBox has security baked in with it's core security interceptor, so this should be easy....

ColdBox 3 (I am using M6 version) gives us a .cfc based config file, and this is where I will be declare the security interceptor.

view plain print about
1//Interceptors
2interceptors = [
3 //security
4 {class="coldbox.system.interceptors.security",
5 properties={rulesSource="xml",
6 rulesFile="/config/securityRules.xml.cfm",
7 debugMode="false",
8 preEventSecurity="true"}}    
9    ];

From the above you can see I have told the interceptor where to find my security rules. In this example I have placed my security rules in an xml file called 'securityRules.xml.cfm'. But these rules could also be pulled from a database, model and ORM etc.

Now lets have a look at the rules in this file...

view plain print about
1<?xml version="1.0" encoding="ISO-8859-1"?>
2<!--Security rule
3ex: All events in the user handler
4 user\..*
5ex: All events
6 .*
7ex: All events that start with admin
8 ^admin
9If you are not using regular expression,
10just write the text
11that can be found in an event.-->

12
13<rules>
14 <rule>
15 <whitelist>
16 general\..*,
17    login\..*
18 </whitelist>
19 <securelist>
20 dashboard\..*
21 </securelist>
22 <roles>user,admin</roles>
23 <permissions>read,write</permissions>
24 <redirect>login.index</redirect>
25 </rule>
26</rules>

As you can see we have a 'whitelist' of events that will not be verified by the security interceptor. We also have a 'securelist'. In my example this means that any event starting 'dashboard' will be secured and redirected to 'redirect' rule, in this case it's the event login.index.

Roles in my case mean that only users with the role assigned of 'user' or 'admin' will be allowed to visit the secure list of events.

That's it! We have setup our role based security in ColdBox. Now lets look at a simple login event. This event fires after the user has clicked login and it's where I will be validating their login credentials.

view plain print about
1/* validate login credentials */    
2function validateCredentials(any){
3    var rc = event.getCollection();
4    var userBean = "";
5    userBean = userService.new();//new object
6    populateModel(userBean);//populate object from scope
7    userCount = userService.countWhere(entityName="user",
8 user_name="#userBean.getuser_name()#",
9    user_password="#userBean.getuser_password()#");
10        
11    if (userCount eq 1){//correct login
12    userBean = userService.findUser();
13    userService.save(userBean);//update user login details
14    loginUser(username=userBean.getuser_name(),
15 password=userBean.getuser_password(),
16 role=userBean.getuser_role());
17    return true;            
18}
19    else {
20return false;
21}
22    }

Because I am using CFScript for my components you can see that I have to call another function called 'loginUser'. loginUser is just inside a none script based CFC that I call by extending this component. for example....

view plain print about
1<cffunction name="loginUser" returntype="void" output="false">
2<cfargument name="username" required="true">
3<cfargument name="password" required="true">
4<cfargument name="role" required="true">
5<!--- log the user in --->
6    <cflogin
7    idletimeout = "1800">

8
9     <cfloginuser
10     name = "arguments.name"
11 password = "arguments.password"
12     roles = "arguments.role">

13    </cflogin>
14
15</cffunction>

The reason for this is that CF9 does not have a script version of login.

That's really it, I have now secured my events based on user roles. For more reading visit the ColdBox Doc's

Oct06

Simple create in ColdBox using ORM CF9

In my last post I showed you how to set-up ColdBox with ORM. I also showed you how to use your service layer within your handlers. Today, an example of how to create a new record in ColdBox using ORM.

Let's use a real pretend example for this. Fake Jake has the following issue he wishes to address.

Jake wants to create a simple sign-up form on his website. He is already using Coldbox M6 and wants to use ORM to create a database with user information and populate it with a simple sign-up form. He has already followed the example post on how to set-up ORM within CB.

Well Jake, first you will need to create the Domain Object for the user sign-up. Nothing complicated about this only a few fields will be needed. However, I have reminded Jake to set-up the event handler correctly within in his Application.cfc. This is done by adding the ORMEventHandler.cfc to the model folder and making sure this 'eventhandler' attribute is 'ORMEventHandler.cfc'

Continue Reading

Oct03

Head Spin Moment ORM many-to-many Help?

I am trying to understand if this is correct way of looking at ORM and a many-to-many relationship.

Below I have two tables. Users and Monsters. A user can have many monsters, and a monster can have many users. Therefore I have a many-to-many relationship. Now I decide to include a join table called mostercollected to normalise the table somewhat. So below is what I come up with.

view plain print about
1/**
2* user
3*/

4component output="false" persistent="true" {
5
6property name="user_id" column="user_id" type="numeric"
7ormtype="int" fieldtype="id" generator="increment";
8
9property name="user_name" column="user_name"
10type="string" ormtype="string";
11    
12     /* link tables */    
13property name="monsters" fieldtype="many-to-many"
14CFC="monsters" FKColumn="user_id" singularname="monsters"
15inversejoincolumn="monster_id" linktable="monstersCollected";
16
17 users function init() output=false{
18 return this;
19 }
20
21}
22
23
24
25
26/**
27* monsters
28*/

29component output="false" persistent="true" {
30
31property name="monster_id" column="monster_id" type="numeric"
32ormtype="int" fieldtype="id" generator="increment";
33
34property name="monster_name" column="monster_name" type="string"
35ormtype="string" ;
36
37/* link tables */
38property name="users" fieldtype="many-to-many" CFC="users"
39FKColumn="monster_id" singularname="monsters"
40     inversejoincolumn="user_id" linktable="monstersCollected";
41
42 monsters function init() output=false{
43 return this;
44 }
45
46}
47
48
49 /* Join table */    
50
51
52
53component entityname="UserMonster" persistent="true" accessors="true"
54table="monstersCollected"
55{
56 property name="user_id"
57 fieldtype="id,many-to-one"
58 cfc="users"
59 cascade="all"
60 fkcolumn="user_id";
61
62 property name="monster_id"
63 fieldtype="id,many-to-one"
64 cfc="monsters"
65 cascade="all"
66 fkcolumn="monster_id";
67
68}

Now if I dump a user to screen, yes I can see all the monsters that each user has (cool), but the array continues down more, showing all monsters and all users that belong to that monster, effectively repeating data (bad, right?).

  • User1
    • Monster2
      • User1
      • User2
    • Monster1
      • User1
      • User2
  • User2
    • Monster2
      • User1
      • User2
    • Monster1
      • User1
      • User2

My concern is that of performance. If every time I want to get a user and I then get monsters + monster again and users that belong to that monster (head spin, moment), this seems like a lot of overhead when all I want is a list of the following...

  • User1
    • Monster2
    • Monster1
  • User2
    • Monster2
    • Monster1

Is this the issue I am making it out to be? Or have fundamentally missed the boat on this one and misunderstood completely?

Sep20

My First ColdBox ORM Setup

As promised I will be posting on my own experiences in setting up CF9's inbuilt ORM with ColdBox. Most of this will be for my own reference.

For this example I am using the M6 release of ColdBox so some of this may change by the final release.

Right, let's start.

First like a normal CF9 ORM project you have to tell your application you are using ORM. ColdBox has it's own set of tools which help integrate hibernate. The first is a must if you're going to use hibernate within CB, and that's the event handler! I would suggest reading up on the ORM event handler as it does a lot more and shows you how to setup Autowire to inject objects into your entities etc.

view plain print about
1// ORM Setup
2    this.ormEnabled = true;
3    this.datasource = "myDS";
4    this.ormSettings = {
5        dbcreate = "update",
6        dialect = "MicrosoftSQLServer",//Specifies the dialect.
7        logSQL = true,
8        eventhandling = true,
9        eventhandler = "model.ORMEventHandler",
10        flushAtRequestEnd = false
11    };

As you can see you have added eventhandling = true, and eventhandler = "model.ORMEventHandler" to the code above. You will now need to add the ORMEventHandler.cfc to your model folder (providing you are following the same folder structure of course).

Next I am going to setup my first Domain Object. Depending on how your using it you will need to create this in the same model folder.

For this example we will setup a simple object and I will assume you already have some understanding of this.

Continue Reading

Aug31

Dear ColdBox

It's been hard for me to get my head around CF9 ORM and ColdBox. The first mistake was using ORM within ColdBox for the first time. My life would have been easy if I had just started at the beginning with ORM. Why did I do it! Why!

Anyhow, I am committed! Truly, exciting and frustrated at the same time. The ColdBox support group is really helpful and if I may say incredibly patient at helping me with my stupid questions!

Over the next few weeks I am going to write up my own experiences with ORM and set up a demo using the M6 version of ColdBox. It won't be from an authority point of view, but from a beginners venture into ORM. In the mean time I want to just remind people of a post Luis made about community and support.

Post Here

Luis gives back so much with this Framework it's made my life a lot easier, if it's helped you, then why not do your bit to.

Aug29

Layer Example Added to RIAForge

I have had requests for an example of the CFC I used in the "Creating a simple Layar with ColdFusion" Tutorial. I decided to comment on the CFC and upload it to RIAForge. So if anyone wants it you can find the project there

It's only a example of what's needed to create POI's and Actions. POI, and objects. However you should be pulling these from a database!

I would love to know what others are doing with Layar at the moment.

Aug06

More Entries