Posted in | Posted on 02-27-2010 | 8,195 views
I've blogged about Framework One (FW/1) a few times before. The more I look at it, the more I grow to like it and appreciate it's way of doing things. I don't prefer it over Model-Glue, but I think it's got a lot going for it, and I think it will appeal to people who may not like Model-Glue. One of the biggest differences between FW/1 and Model-Glue is that almost everything you do in FW/1 is implicit in nature. There is no XML. There is no set of declarations for each event. Instead, the framework will do almost everything for you and save you from writing a lot of code that - for the most part - isn't strictly necessary. This post isn't meant to teach you FW/1 - see the docs for that. Rather I thought I'd share my experiences (and code!) for my first "real" application. Before I go any further though - please keep in mind: This is my FIRST FW/1 application. Do you remember your first ColdFusion application? Yeah - this is worse. I'm sure Sean and others who have used FW/1 will be able to tear this apart. That being said - I enjoyed writing this, and I enjoyed using the framework. I hope this sample is useful to others in some way.
So what did I build? My application is called QBall. It's based on the recent rise of "Question/Answer" sites like Stack Overflow. Basic functionality includes:
- User registration and login. Later on I plan on adding the ability to let you edit your information and see the content you have contributed.
- Users can write questions. Questions are open ended blocks of text on any topic. Later on I'd like to add some basic tagging.
- Users can write answers to questions.
- Users can vote up and vote down answers to show their support.
- The user who wrote the question can select an answer as the one they accept as best.
So as you can see, there really isn't a lot going on here. The home page shows the most recent questions along with their current status:

Here is a screen shot of a new question:

And finally a shot of a question with a few answers:

To use this application you will need the FW/1 framework (of course) which is all of one file. You will also need ColdFusion 9. I made use of script-based CFCs and ORM for all my data entry. Create a virgin database and setup a DSN called "qball" before running the application. After you've done that, it should "just work". If it doesn't, let me know. Actually - one thing that may not work for you is the mapping. I believe the docs typically show an "org" mapping for the FW/1 code. I created a mapping called fw1 instead. Whichever you chose, make note of it in line one in the Application.cfc file:
Most likely you will need to tweak that.
Ok, so what did I like - and what caused me a bit of trouble? Well for the most part, the thing that took me the longest to wrap my head around was the start/end cycle of controller calls. When you run x.y, FW/1 will look for an execute a startY method in your x controller, then the Y method, then the Y method of the X service, and finally endY back in the X controller. Having just looked over what I wrote I don't think that makes much sense (again, check the docs). That's somewhat different than what I'm used too and it took a little bit to get used to the "flow". Once I did though I didn't have much trouble putting it to use. Another thing that was a bit difficult was handling cases where the implicit actions done by FW/1 weren't exactly what I want.
Anyway - download it and check it out.
Edited February 28, 7:37 AM: Please note that QBall requires ColdSpring to be installed. I've updated the code to not use x.y.z in the entity relationships. Thanks to Andreas for that. I also fixed the dbdefault for answer.cfc (and again, thank you Andreas).


Great to see you jumping in to FW/1.
I installed your app on Apache/CF9 a Mac and PC, but in both cases running it gives me an error stating:
Exception in
An association from the table answer refers to an unmapped class:
(org.hibernate.MappingException)
This is followed by a cfdump with about 60 recursive instances of the same error. No tables are created.
It seems you are using coldspring in this app, although it is not mentioned in your post - is this a dependency? .... I thought this might be the issue, but already have a CF Mapping to a coldspring install.
Any idea what I am doing wrong?
I assume you are referring to http://cfrails.riaforge.org in your post? I haven't tried that. I'll take a look at it.
~ Ben
I ran into the same problem as @Rob. This seems to happen, when running the app in a subdirectory below webroot. Doing a quick-fix by removing the "model." prefix in answer.cfc and question.cfm (many-to-many properties cfc=) brought up another ORM error. Hibernate did not like the dbdefault="false" entry for property selectedanswer, when creating the tables for the first time (applies to both derby and ms-sql). Replacing false with 0 did the trick - and voila. Ready for playing around with the app.
BTW: I didn't check whether my above changes would break the application when running in webroot, was too busy trying out the features ...
@Rob: Should be fixed now - get latest download.
@Andreas: Thank you for your tips. I changed the relationships to just point to each other directly, no model.x. I've had issues w/ orm before where things will get cached and a full CF restart is necessary for CF to recognize that something exists in a new place. Anyway, the code has been updated.
I also documented the need for ColdSpring. Totally forgot about that and I assumed everyone used it. ;)
Thanks much for the example app! I've learned a few very interesting things studying it. A question for the QBall, if you have a moment.
What's the advantage of using an ORM style query? Or is it more that you're just trying it out?
Typically - I use entityLoadByPk to get one record, entityLoad to get them all, and ormExecuteQuery when I'm doing _any_ type of filtering.
Why ormExecuteQuery instead of SQL within the familiar cfquery tag ... could be you're simply sharpening your skillset, could also be that there's another motivation.
?
So in another words, if what I say makes sense now, I reserve the right to come back later and say it was dumb. ;) I also HIGHLY encourage folks to argue with me here as I definitely am NOT the "Jedi" of this.
So why HQL and not a regular CFQUERY? I feel like if I'm using Hibernate to manage my DB interactions, then I should strive to always do that. So HQL to me makes the most sense. I'm basically being consistent with the framework I use to access and work with my data.
Have you figured out how to set values to null using CF Hibernate like you can with a cfqueryparam? eg:
cfqueryparam
value="#arguments.getEndTime()#"
cfsqltype="cf_sql_datetime" null="#NOT
isDate(arguments.getEndTime())#"
I don't find anything in the docs ...
ob.setFoo(javaCast("null",""))
?
Good to see you on FW/1. After seeing QBall code I am able to explore Framework-one :)
Thank you so much
Thanks for sharing Ray ... :)
i have a problem with you sample app on cf 9.0.1 (with a apache derby embeded database)
when trying to "register" in qball i get errors:
1)no file views.main.error caused by #2
2)data undefined in rc
what could be the problem?
thanks for your help
Found out this in the docs
"
Prior to FW/1 2.0, a service method was automatically called, with a name that matched the action and the result was placed in rc.data. FW/1 1.2 introduced a configuration variable to control this behavior and that variable is still present in 2.0, but the default behavior has changed so that service methods are not called automatically.
"
so i had to call them manually in the controllers
structure insider Application.cfc
"suppressImplicitService=false".
It will look like
variables.framework = {
reloadApplicationOnEveryRequest=false,
suppressImplicitService=false
};
Once it is done, the app will work.
[Add Comment] [Subscribe to Comments]