Entries for month: August 2007
As all good software developers know...
Posted by [Justice] in omgwtf on August 20, 2007
SY0-101 pros who are done with the actual tests of 70-649 as well as 70-270 usually move towards software development. Thos who have not done their 646-204 are not qualified for this though.
using Decorators with Transfer ORM
Posted by [Justice] in Coldfusion , Transfer ORM on August 20, 2007
Transfer is a system that will allow you to abstract your database from your code, and use a more generic way of accessing your data (as well as a slew of other very cool things). Once it is configured, Transfer will auto-generate methods you can use to read / list / update, and save data to your (insert database software here) server.
Anyway, lets say you have a very simple table, users. You have an ID, fName, lName, etc. Your transfer config could look like this:
Your object name is your alias, this will be how you refre to it using Transfer. The table is (duh) your database table name, and the ID / property fields define each column in your database. Im not gonna get deeply into the nitty gritty of instancing Transfer or anything, but with this config, Transfer will generate methods to access your data.
Now, on to decorators =)
In case you dont know, the documentation says this about a decorator: "A decorator is used when you wish to write your own CFC to be used to represent data, in place of the Transfer generated Object."
Lets change 1 line in our transfer configuration:
Now, any methods we have inside of our some.path.to.a.cfc will be included when you create an instance of your user record! You can even over-write built in functions, replacing or supplementing them with your own. You could add a getInvoices() function that, once your user is instances and loaded (using get), you can call getInvoices() to return all invoices for the instanced user. Or, you can build additional functions over top of auto-generated transfer ones. I am digging Transfer, and I love how extensible it is!
Anyway, lets say you have a very simple table, users. You have an ID, fName, lName, etc. Your transfer config could look like this:
<br /><object name=<span class='cc_value'>"user"</span> table=<span class='cc_value'>"Users"</span>><br /> <id name=<span class='cc_value'>"ID"</span> type=<span class='cc_value'>"numeric"</span> /><br /> <property name=<span class='cc_value'>"fName"</span> type=<span class='cc_value'>"string"</span> column=<span class='cc_value'>"fName"</span> /><br /> <property name=<span class='cc_value'>"lName"</span> type=<span class='cc_value'>"string"</span> column=<span class='cc_value'>"lName"</span> /><br /></object><br />Your object name is your alias, this will be how you refre to it using Transfer. The table is (duh) your database table name, and the ID / property fields define each column in your database. Im not gonna get deeply into the nitty gritty of instancing Transfer or anything, but with this config, Transfer will generate methods to access your data.
<br /><span class='comment'></span><br /><cfset myUser = transfer.get(<span class='cc_value'>"user"</span>, userID) /><br /><br /><span class='comment'></span><br /><cfset myUser.setfName(<span class='cc_value'>"Harry"</span>) /><br /><cfset myUser.setlName(<span class='cc_value'>"Smith"</span>) /><br /><br /><span class='comment'></span><br /><cfset myUser.save() /><br />Now, on to decorators =)
In case you dont know, the documentation says this about a decorator: "A decorator is used when you wish to write your own CFC to be used to represent data, in place of the Transfer generated Object."
Lets change 1 line in our transfer configuration:
<br /><object name=<span class='cc_value'>"user"</span> table=<span class='cc_value'>"Users"</span> decorator=<span class='cc_value'>"some.path.to.a.cfc"</span>><br />Now, any methods we have inside of our some.path.to.a.cfc will be included when you create an instance of your user record! You can even over-write built in functions, replacing or supplementing them with your own. You could add a getInvoices() function that, once your user is instances and loaded (using get), you can call getInvoices() to return all invoices for the instanced user. Or, you can build additional functions over top of auto-generated transfer ones. I am digging Transfer, and I love how extensible it is!
Layers upon layers - model, controllers, and views, oh my!
Posted by [Justice] in Coldfusion , Model-Glue on August 14, 2007
I had an interesting conversation with Sean Corfield last night, and while my understanding may be imperfect as of yet, here is what I came away with (I was asking for clarification as to some design patterns for object oriented coding)
The Model - the model should be pretty dumb, this would be the portion of the code that accesses your data. If you use Transfer or Reactor, they would be part of your model. I have several functions that call Transfer, for example:
These basic dumb getters are also part of my model.
Services - Services provide an interface to your model. For example, I may have a user service with many functions that are application specific. UpdateUser, registerUser, etc. These service functions will make calls to my model (which are the basic getters / setters) and basically route my data to the proper places. My service for user could also be responsible for creating a userBean to persist across the session.
Controller - the controller should handle incoming data from the user, and pass it to the appropriate controller. No application logic will reside in the controller, and in the case of Model Glue: Unity, the controller would be your ModelGlue.xml file. This simply recognizes where the user needs to be directed, and then passes incoming variables from the url and form into whichever service is required.
View - The view is simply display code. This is the only place that display code goes. Your services should make any necessary variables available to the view explicitly, and your view should never interact directly with the URL or Form scopes. If you need variables, your service layer should process those incoming variables (which it got from your controller) and place them into a scope that the view can access. When in model-glue, and inside a controller, you access those variables like this:
From within your view, you access your variables like this:
Its slow going for me, but I think I am getting a better grasp on the how, and I am getting the feel for the Why, but the why is a bit more slippery =) More to come as I grok it further.
The Model - the model should be pretty dumb, this would be the portion of the code that accesses your data. If you use Transfer or Reactor, they would be part of your model. I have several functions that call Transfer, for example:
<br /><cffunction name=<span class='cc_value'>"getItemsByAuctionID"</span> access=<span class='cc_value'>"public"</span> returntype=<span class='cc_value'>"void"</span> output=<span class='cc_value'>"false"</span>><br /> <cfargument name=<span class='cc_value'>"event"</span> type=<span class='cc_value'>"any"</span>><br /> <br /> <cfset var items = getTransferFacade().listByProperty(<span class='cc_value'>"item"</span>, <span class='cc_value'>"auctionID"</span>, arguments.event.getValue(<span class='cc_value'>"auctionID"</span>), <span class='cc_value'>"sortOrder"</span>) /><br /><br /> <cfset arguments.event.setValue(<span class='cc_value'>"items"</span>, items) /> <br /> <cfreturn /><br /></cffunction><br />These basic dumb getters are also part of my model.
Services - Services provide an interface to your model. For example, I may have a user service with many functions that are application specific. UpdateUser, registerUser, etc. These service functions will make calls to my model (which are the basic getters / setters) and basically route my data to the proper places. My service for user could also be responsible for creating a userBean to persist across the session.
Controller - the controller should handle incoming data from the user, and pass it to the appropriate controller. No application logic will reside in the controller, and in the case of Model Glue: Unity, the controller would be your ModelGlue.xml file. This simply recognizes where the user needs to be directed, and then passes incoming variables from the url and form into whichever service is required.
View - The view is simply display code. This is the only place that display code goes. Your services should make any necessary variables available to the view explicitly, and your view should never interact directly with the URL or Form scopes. If you need variables, your service layer should process those incoming variables (which it got from your controller) and place them into a scope that the view can access. When in model-glue, and inside a controller, you access those variables like this:
<br /><cfset myVar = arguments.event.getValue(<span class='cc_value'>"myURLorFormVar"</span>) /><br /><cfset arguments.event.setValue(<span class='cc_value'>"myVariableName"</span>, myVariableValue) /><br />From within your view, you access your variables like this:
<br /><cfset viewstate.setValue(<span class='cc_value'>"pageTitle"</span>, <span class='cc_value'>"This is my title"</span>) /><br /><cfset myLocalVar = viewState.getValue(<span class='cc_value'>"varNameFromEvent"</span>) /><br />Its slow going for me, but I think I am getting a better grasp on the how, and I am getting the feel for the Why, but the why is a bit more slippery =) More to come as I grok it further.
Secure your Model-Glue XML files from prying eyes
Posted by [Justice] in Coldfusion , Model-Glue on August 9, 2007
I sent an email to Ray Camden a few months ago to let him know that his application XML for one of his sites was exposed, showing off his logic basically. He mentioned that you can change those XML files to be .cfm and do some tweaking to hide them from other people, but it sounded like a pain. Read on how to fix!
Using iText to compile multiple Tiff images into a PDF
Posted by [Justice] in Coldfusion on August 1, 2007
We have invoices and ancillary documents that need to be bundled together, so I used iText to take a comma-seperated list of Tiff paths and return a PDF file. Enjoy!
<br /> <cffunction name=<span class='cc_value'>"writePdfFromTiffs"</span> output=<span class='cc_value'>"false"</span> returntype=<span class='cc_value'>"string"</span> hint=<span class='cc_value'>"This will output a .pdf file containing multiple tiff images"</span>><br /> <cfargument name=<span class='cc_value'>"pdfOutput"</span> required=<span class='cc_value'>"true"</span> type=<span class='cc_value'>"string"</span> hint=<span class='cc_value'>"Provide a full path to output your PDF too"</span>><br /> <cfargument name=<span class='cc_value'>"tiffList"</span> required=<span class='cc_value'>"true"</span> type=<span class='cc_value'>"string"</span> hint=<span class='cc_value'>"Provide a comma deliniated list of tiff images to include"</span>><br /><br /> <!--<span class='cc_comment'>-// This code was modified from code provided by bryan@electricedgesystems.com, thanks a ton! //---><br /><br /></span> <!--<span class='cc_comment'>-// Declare local variables to keep everything clean //---><br /></span> <cfset var cb = /><br /> <cfset var curFile = /><br /> <cfset var ra = /><br /> <cfset var comps = /><br /> <cfset var i = /><br /> <cfset var img = /><br /> <cfset var writer = /><br /> <cfset var TiffImage = /><br /> <cfset var PdfFile = /><br /> <cfset var Document = /><br /> <cfset var Image = /><br /> <cfset var Paragraph = /><br /> <cfset var PdfContentByte = /><br /> <cfset var PdfWriter = /><br /> <cfset var RandomAccessFileOrArray = /><br /><br /> <!--<span class='cc_comment'>-// Opan file system I/O to write pdf too //---><br /></span><cfset PdfFile = createObject(<span class='cc_value'>"java"</span>,<span class='cc_value'>"java.io.FileOutputStream"</span>).init(arguments.pdfOutput)><br /> <!--<span class='cc_comment'>-// Init the text.document object //---><br /></span><cfset Document = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.Document"</span>).init()><br /> <!--<span class='cc_comment'>-// Create pagesize argument so I can set new page sizes //---><br /></span> <cfset PageSize = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.PageSize"</span>) /><br /> <!--<span class='cc_comment'>-// Init the text.image object //---><br /></span><cfset Image = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.Image"</span>)><br /> <!--<span class='cc_comment'>-// Create our default paragraph object to contain our images //---><br /></span><cfset Paragraph = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.Paragraph"</span>)><br /> <!--<span class='cc_comment'>-// not sure what this does, but it needs to be here //---><br /></span><cfset PdfContentByte = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.pdf.PdfContentByte"</span>)><br /> <!--<span class='cc_comment'>-// Create PDFWriter class //---><br /></span><cfset PdfWriter = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.pdf.PdfWriter"</span>)><br /> <!--<span class='cc_comment'>-// Create array to contain image //---><br /></span><cfset RandomAccessFileOrArray = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.pdf.RandomAccessFileOrArray"</span>)><br /> <!--<span class='cc_comment'>-// Load TIFF image handling //---><br /></span><cfset TiffImage = createObject(<span class='cc_value'>"java"</span>, <span class='cc_value'>"com.lowagie.text.pdf.codec.TiffImage"</span>)><br /> <!--<span class='cc_comment'>-// Assign the page size //---><br /></span> <cfset document.setPageSize(PageSize.Letter) /><br /> <!--<span class='cc_comment'>-// Set page margins to all 10 //---><br /></span><cfset document.setMargins(10,10,10,10) /><br /> <!--<span class='cc_comment'>-// Create instance of writer //---><br /></span><cfset Writer = PdfWriter.getInstance(document, PdfFile)><br /><br /> <cftry><br /> <!--<span class='cc_comment'>-// Open document for writing //---><br /></span><cfset document.open()><br /> <cfset cb = writer.getDirectContent()><br /><br /> <!--<span class='cc_comment'>-// Loop through list of files provided as an argument and add each to our pdf //---><br /></span><cfloop list=<span class='cc_value'>"#arguments.tiffList#"</span> delimiters=<span class='cc_value'>","</span> index=<span class='cc_value'>"curFile"</span>><br /> <!--<span class='cc_comment'>-// Check this file to make sure it is a Tiff //---><br /></span> <cfif right(curFile, 3) eq tif or right(curFile, 4) eq tiff><br /><br /> <!--<span class='cc_comment'>-// Catch - try to account for un-accessable files or 32 bpp tiffs<br /></span> 32 bit tiffs not supported by iText<span class='cc_comment'> //---><br /></span> <cftry><br /><br /> <!--<span class='cc_comment'>-// stuff file into memory //---><br /></span> <cfset ra = RandomAccessFileOrArray.init(curFile)><br /><br /> <!--<span class='cc_comment'>-// read file and determine number of pages in TIFF //---><br /></span> <cfset comps = TiffImage.getNumberOfPages(ra)><br /><br /> <!--<span class='cc_comment'>-// loop over number of pages and add each one to the PDF //---><br /></span> <cfloop index=<span class='cc_value'>"i"</span> from=<span class='cc_value'>"1"</span> to=<span class='cc_value'>"#comps#"</span>><br /> <cfset img = TiffImage.getTiffImage(ra,javacast(<span class='cc_value'>"int"</span>,i))><br /> <cfset img.scaleToFit(592, 772)><br /> <cfset img.setAbsolutePosition(10,10)><br /> <cfset cb.addImage(img)><br /><br /> <!--<span class='cc_comment'>-// force new page after each image is added //---><br /></span> <cfset document.newPage()><br /> </cfloop><br /><br /> <cfcatch type=<span class='cc_value'>"any"</span>><br /> <!--- Ignore, un-supported file type<span class='cc_comment'> //---><br /></span> </cfcatch><br /> </cftry><br /> </cfif><br /> <!--<span class='cc_comment'>-// Close each file after a loop //---><br /></span> <cfset ra.close()><br /> </cfloop><br /><br /> <!--<span class='cc_comment'>-// close document, this will write the pdf to the filesystem //---><br /></span><cfset document.close()><br /><br /> <!--<span class='cc_comment'>-// Return success //---><br /></span> <cfreturn Success /><br /><br /> <!--<span class='cc_comment'>-// Catch any errors and return failed //---><br /></span> <cfcatch type=<span class='cc_value'>"any"</span>><br /> <cfreturn Failed /><br /> </cfcatch><br /> </cftry><br /> </cffunction><br />
Recent Comments