Raymond Camden's Blog Rss

Framework One Sample Application - QBall

27

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:

view plain print about
1component extends="fw1.framework" {

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).

Download attached file

Comments

[Add Comment] [Subscribe to Comments]

Thanks for this Ray, I've just started working with FW/1 myself. I have not been much of a frameworks supporter since Fusebox went past version 2, however I do like the convention over configuration paradigm alot and from what I've seen so far with FW/1 it's going to save me a lot of time for certain implementations.
Ray - Have you worked with CFRails? I lost my virginity to frameworks recently (with FW/1) and after a quick scan of CFRails, it seems to be pretty simple too and was thinking of going to the next level. So, if you or any of the viewers/commenters have feedback, please let me know. I dont think I am quite ready for beans yet.
Hi Ray,

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?
@ CFer ~ Have you tried CFWheels? http://cfwheels.org
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
@Ben - No, I haven't tried CFWheels yet. I started going through it a few days back and then stumbled upon the http://cfrails.riaforge.org and it looked like simpler but it didn't register that they were both Rails related frameworks. I need to research what the differences are between the two.
I became a fan of FW/1 recently and I want to thank you for sharing another useful sample application making use of this new kid on the framework block.

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 ...
@CFer: I have not looked at CFRails yet.

@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 Ray... working fine now.
Ray,

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?
I want to be clear - when you say "ORM style query" do you mean ORM in general, or HQL?
HQL.
To over simplify things, there are 2 main ways to fetch data. entityLoad and ormExecuteQuery. entyityLoad lets you filter the data, ie, all people with gender="F", but it doesn't let you _search_, ie, all people who have a name like '%ray%'. So one reason to use HQL is for searches. Also, HQL allows for more complex filtering than what you can do with entityLoad.

Typically - I use entityLoadByPk to get one record, entityLoad to get them all, and ormExecuteQuery when I'm doing _any_ type of filtering.
Thanks for the comments Ray. As often, you're a CF pioneer.

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.

?
Before I say anymore, let me stress. I am an ORM newbie. I have one large ORM app under my belt (Picard, not yet released), but I"m still fumbling around this area like everyone else. I look at it like CFCs. When CFCs first came out, the way I used them is FAR different than how I use them now.

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.
Ray,

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 ...
Can't you just use

ob.setFoo(javaCast("null",""))

?
That works wonderfully Ray. Thanks. I'm in the middle of catching up after many months away from CF, so some of these details I just haven't absorbed yet. I was somehow expecting and searching for a native CF function to set a null value, along the lines of the new isNull() function, but couldn't find it. It's amazing how quickly things have progressed.
Ray Thanks for the javaCast example. I was scouring the web looking for how to set a null value in CF9 ORM. Why isn't this in the Adobe docs!
@Ray
Good to see you on FW/1. After seeing QBall code I am able to explore Framework-one :)

Thank you so much
Hey Ray, I'm trying to learn fw/1. I think it easier for me to learn when there's a sample of code like this. You posted that this sample application can be downloaded, but i didn't found the link. Where can i download this?

Thanks for sharing Ray ... :)
At the end of the blog entry look for the download link.
ah there they are, i found it. Thx ray .. :)
Hi 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
Um... no idea. It's been two years since I worked with this sample. If you are using the latest FW/1, it's possible my code is WAY out of date now.
indeed your code is no more compliant with that version of FW/1
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
Add below config inside variables.framework{}
structure insider Application.cfc
"suppressImplicitService=false".

It will look like
variables.framework = {
      reloadApplicationOnEveryRequest=false,
      suppressImplicitService=false
   };

Once it is done, the app will work.
I'll give it a try, thanks!

[Add Comment] [Subscribe to Comments]