Building your first Model-Glue application - The Final Battle

Ok, pardon the dramatic title. I guess I'm just happy to be wrapping this thing up. I loved writing it, but it certainly turned out to be more work than I thought it was going to be. To be honest, I'm not terribly surprised. If there is one thing I've learned in my years as a web developer, even the simplest project can turn out to be more complex than you (or the client) can imagine. I had hoped to cover a complete application, and I did, but I definitely cut a few corners towards the end. Sorry! I do hope that those of you who haven't looked into a framework yet will give Model-Glue a shot with your own development developments. So let me talk a bit about what I didn't cover, and what could have been improved.

Security

Those of you who read my blog regularly know that I'm a bit of a security nut, specifically when it comes to the proper checking of input variables. By that I mean form, url, cookie, and any value that is not directly controlled by your code. I find myself not being as anal as I normally would be. I think it's a visual problem. I'm so used to seeing URL, or FORM, and immediately thinking "Have I properly checked this variable?" Because Model-Glue abstracts this into the Event object (which is a good thing, don't get me wrong), I find myself forgetting to be as secure as I normally would be. Again - this is my fault and something I'll have to work as I write more Model-Glue applications. I point it out as I definitely noticed a few places I could have improved my checking in the PhotoGallery application.

Error Handling

Out of the box, Model-Glue will automatically fire an event, Exception, when an error occurs. One thing the PhotoGallery application needs is a nicer error handling template. Right now it just reports that an error has occurred. It would be trivial to add some simply code to email the exception to the owner. You can't assume your users will tell you about errors. (Shoot, I can tell you that I've sent hundreds of error reports to sites and only one in ten bother to write me back and thank me.) This is definitely not a Model-Glue suggestion, but a suggestion for all of your web sites. It takes about five minutes and can help you keep in touch with your web site.

Logging

One thing I tend to do a lot in my applications is logging. I probably would have added a lot more logging to this application if it were a real live production site. I'd log user creation, updates, new gallery, image uploading, etcetera.

While not exactly "logging", I would have used more metadata for my database tables. I mentioned this normally whenever I was describing a particular table. By metadata I simply mean a record of when a record was created and when it was last updated. I sometimes I also record the username of the user who last modified the record.

The End

Thank you to everyone who commented on the series and helped keep me on topic. Attached to entry is a zip that contains not only the source code (with a SQL Server database creation script), but also PDF copies of this entry and all the earlier articles. (To be honest, the zip will not contain this entry until about five minutes after I post - just in case your reading this entry immediately after I posted it.) If someone takes the photo gallery application and actually uses it, please let me know. Post the URL to this entry and share it with everyone else.

EDITED:

Emmet McGovern created an "uber" PDF that joins all the individual PDFs in one PDF. The zip still contains the individual PDFs as well. I did not update the file attached to this entry. In fact, I'm going to delete it. Please use the link in the right hand pod: http://www.coldfusionjedi.com/downloads/mgapp.zip

Comments

Thank you for going through the steps and letting us watch you think! Your explanations were just right for the amount of detail and what was left to the reader. I had to bow out around step 8 for work and then vacation considerations, but I'll finish up with the zip and then give MG a try on one of my own apps!

Again, thank you for doing this!
# Posted By Edward T | 4/10/06 6:15 AM
First of all Thank You for a great series Ray. I started up development of two MG apps in work right about the time of your first post, and following you along has been a GREAT help.

And also I used your code (with some changes to have it run with MySQL 4.1) to set up a gallery showing of the current renovation development of our "new" house.

If you are interested you can find it at: http://gallery.ulseth.no/index.cfm?event=viewgalle...
# Posted By Trond Ulseth | 4/10/06 6:31 AM
Wonderful work, Ray. I don't suppose you'd consider compiling your articles into e.g. a single PDF for us to easily print off and read (while on the thinking chamber)?
# Posted By Damien | 4/10/06 8:51 AM
Hmmm. I don't have any native ability to do that. Does Acrobat allow you to open a PDF and edit it? (I've never used it.) If so, someone could simply load my 10 PDFs into one PDF.
# Posted By Raymond Camden | 4/10/06 8:54 AM
If you compile them all as e.g. a Word or OpenDocument file I'll try converting it to a PDF for you.
# Posted By Damien | 4/10/06 8:59 AM
Ray -

If I remember correctly, if you have Acrobat Pro, you can create a PDF from other PDFs.
# Posted By Scott Stroz | 4/10/06 10:10 AM
I've removed the attachement to this entry. Please download the code from here:

http://ray.camdenfamily.com/downloads/mgapp.zip

Emmet graciously made an uber pdf, and thanks to everyone else who offered.
# Posted By Raymond Camden | 4/10/06 10:53 AM
Great work Ray. I'm building a medium size site and was able to incorporate MG with considerable ease due to your tutorial. It has good explanations with simple examples. Any plan of using ajaxcfc with MG in future?.

One thing that I'm not sure about is when I use MakeEventBean() it doesn't set the default value I have given in my cfargument. I have to explicitly call the set method. Any idea why?.
# Posted By Francis | 4/20/06 3:12 PM
While I have nothing against AJAX, I'm just not turned on by it as much as others are. :) I guess if a client asks for it, I'll add it. I may consider it for the next rev of CFLib.

Can you show me how you are using makeEventBean? it won't take defaults from cfargument. It uses the event scope for data.
# Posted By Raymond Camden | 4/20/06 3:52 PM
Your tutorials on setting a sample application using MG were awesome. I'm building a medium size application and your walk-through helped a lot and saved a lot of time! Big Thanks!
# Posted By Adam Leszinski | 4/20/06 4:12 PM
No problem!
# Posted By Raymond Camden | 4/20/06 4:13 PM
Well in my registration function, I have
<cfset var bean = arguments.event.makeEventBean("clients_mg.model.userBean") /> and this is above all <cfif>s in the function.

My registration page has couple of fields that won't display unless the email domain is in a preapproved list. So I'm checking to see whether the field is displayed or not. If it is already displayed, then I go ahead and submit the form. If it is not displayed, then I check the email domain and display error or field accordingly. So I call
<cfif bean.getUserSite() eq ''> <!--- This checks whether the field is already displayed or not --->

In my userBean.cfc, I have a cfargument with default of 0. But my get method never returns 0 unless I explicitly call

<cfset bean.setuserSite()>
and then check <cfif bean.getUserSite() eq 0>
# Posted By Francis | 4/20/06 4:39 PM
You lost me there Francis. :) I know that the makeEventBean will check the event scope. If the value isn't there, then maybe it wasn't ever in the form? You said the stuff only shows up in certainsituations,right? I guess maybe introspect what is in event. It will only go into the bean if there is a function with the same name, but set in front. In other words, if MG sees form.goober, it will try to run setgoober() on your bean.
# Posted By Raymond Camden | 4/21/06 4:44 PM
:-) You have it right. I had so many things going on and never thought about that. I had to step back and look at it from scratch. Then I found it.

By the way, have you ever done a mvc framework from server standpoint?. Like having the presentation layer in one server and all your business logic in another server?. If so, can you share some of your suggestions or point me in the right direction?.
# Posted By Francis | 4/21/06 7:05 PM
Nope, I haven't. Sorry. :)
# Posted By Raymond Camden | 4/22/06 9:53 AM
Just want to let you know that my very first app that uses model-glue framework in a 3-tier architecture is going live this month. Adobe site doesn't really have any documentation about using EJBs in jboss J2EE server. So after so many sleepless nights and days with headaches, I was able to successfully complete my first web app using model-glue and EJBs. Your series on model-glue application really helped me out. Thanx.
# Posted By Francis | 12/12/06 4:01 PM
No problem. Glad I could help.
# Posted By Raymond Camden | 12/12/06 4:06 PM
Hi! I know I'm responding to an old post here, but I'm currently using this series to help me gain a better understanding of how to pull an app together with Model-Glue.

Is there by any chance an updated version of this application that uses ColdSpring for bean settings vs. the <config> block section in ModelGlue.xml that isn't really used anymore in version 2.0? I'm not certain how to add additional properties in my ColdSpring.xml file the same way you did with the additional <config> block settings (for DSN, admin email, etc) in the ModelGlue.xml file.

I started in on the ColdSpring documentation but was getting confused fast and thought, "I know ColdSpring really speeds up development from what I keep reading, but there must be a simple way to just add some basic application settings such as DSN, etc."

Any suggestions are greatly appreciated!

Thanks!!
Tony
# Posted By Tony Piscotti | 2/1/08 1:19 AM
Unfortunately no. I can say that I too am learning ColdSpring. There is indeed a simple way to do basic stuff like DSN, etc. Consider this bean def:

<bean id="config" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
   <property name="config">
      <map>
         <entry key="dsn">
         <value>foo</value>
         </entry>
      </map>
   </property>
</bean>

You can imagine more settings in here as well. You can then pass this bean to a CFC:


<bean id="answerDAO" class="foo.model.dao.answerdao">
   <constructor-arg name="config"><ref bean="config" /></constructor-arg>
</bean>

And in your CFC do:

<cffunction name="init" access="public" output="false" returnType="answerdao">
   <cfargument name="config" type="any" required="true">
   <cfset variables.dsn = arguments.config.getConfigSetting("dsn")>
   <cfreturn this>
</cffunction>
# Posted By Raymond Camden | 2/1/08 1:29 PM
Thanks, Ray! I will definitely give this a try. I appreciate the help.

- Tony
# Posted By Tony Piscotti | 2/2/08 12:41 PM