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:
component 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).
Archived 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!
I have CF10. I tried to run, but got error "Could not find the ColdFusion component or interface fw1.framework."
In order for CF to find the framework.cfc file, you must either:
a) Create a subfolder called fw1 and place it there.
b) Create a CF mapping in your App.cfc called fw1 that points to the same folder.
c) Do the above, but in the CF Admin.
I recommend A or B.
Exception occured before FW/1 was initialized
(org.hibernate.JDBCException)
I was created table already but it says can't create table.
Um, what? "I was created table already but it says can't create table."
I created dsn "qball".and I did not found where the table is.
can you please explain configuration in steps.
thanks
I steped ahead.
now error is "Element CONTROLLER is undefined in TUPLE."
Sorry, not sure about that one. DoController is failing within FW/1 itself.
Getting :
Exception in onError
The action main.default failed.
Element AUTHENTICATED is undefined in RC.
Are you using the code from my zip or the latest FW/1? This code here is over three years old and if you are using the latest FW/1 it may not work right.
Should I use older fw/1 ?
Um, well. If I were someone learning FW/1, I'd want to use the latest. This blog post is over 3 years old. You must keep that in mind. I'm sure my zip and it's copy of FW/1 would work, but frankly, I'd use the latest FW/1 and just consider my sample a dated example.
This was one of the best examples I found about ColdFusion ORM and Framework One. I updated it and it's now included in the examples of the latest build. https://github.com/framewor...
I am honored. :)
i AM NEW TO FW/1 FRAME WORK. I have downloaded the code from
https://github.com/framewor...
qball is not working.
org.hibernate.JDBCException
Exception occured before FW/1 was initialized
Error code : 102
org.hibernate.JDBCException: Error during DDL export at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:232) at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:178) at coldfusion.orm.hibernate.HibernateConfiguration.exportSchema(HibernateConfiguration.java:482) at coldfusion.orm.hibernate.HibernateConfiguration.exportSchema(HibernateConfiguration.java:434) at coldfusion.orm.hibernate.HibernateConfiguration.initHibernateConfiguration(HibernateConfiguration.java:215) at coldfusion.orm.hibernate.HibernateConfiguration.<init>(HibernateConfiguration.java:183) at coldfusion.orm.hibernate.ConfigurationManager.initConfiguration(ConfigurationManager.java:67) at coldfusion.orm.hibernate.HibernateProvider.InitializeORMForApplication(HibernateProvider.java:184) at coldfusion.orm.hibernate.HibernateProvider.beforeApplicationStart(HibernateProvider.java:80) at coldfusion.filter.ApplicationFilter.fireBeforeAppStartEvent(ApplicationFilter.java:611) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:330) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:42) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:141) at coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:30) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:94) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilte...:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:58) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.CfmServlet.service(CfmServlet.java:219) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:422) at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:198) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: java.sql.SQLException: [macromedia][SQLServer JDBC Driver][SQLServer]Incorrect syntax near 'auto_increment'. at macromedia.jdbc.sqlserverbase.ddcw.b(Unknown Source) at macromedia.jdbc.sqlserverbase.ddcw.a(Unknown Source) at macromedia.jdbc.sqlserverbase.ddcv.b(Unknown Source) at macromedia.jdbc.sqlserverbase.ddcv.a(Unknown Source) at macromedia.jdbc.sqlserver.tds.ddr.v(Unknown Source) at macromedia.jdbc.sqlserver.tds.ddr.a(Unknown Source) at macromedia.jdbc.sqlserver.tds.ddr.a(Unknown Source) at macromedia.jdbc.sqlserver.dda3.m(Unknown Source) at macromedia.jdbc.sqlserverbase.dde7.e(Unknown Source) at macromedia.jdbc.sqlserverbase.dde7.a(Unknown Source) at macromedia.jdbc.sqlserverbase.dde7.v(Unknown Source) at macromedia.jdbc.sqlserverbase.dde7.x(Unknown Source) at macromedia.jdbc.sqlserverbase.dde7.executeUpdate(Unknown Source) at coldfusion.server.j2ee.sql.JRunStatement.executeUpdate(JRunStatement.java:193) at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:227) ... 42 more
Please i just want to know how to execute a query from MSSql server db. If you can give a sample for that. I am trying use this fw/1 for my application with one dynamic page
Kumar - my demo is now far out of date. I recommend looking at the demo apps for FW/1 you can get from the project itself.