Entries for month: August 2007

As all good software developers know...


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.

1 comments

using Decorators with Transfer ORM

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:

<br /><object name="user" table="Users"><br />   <id name="ID" type="numeric" /><br />   <property name="fName" type="string" column="fName" /><br />   <property name="lName" type="string" column="lName" /><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 /><!-- This will retrieve a user record based on userID --><br /><cfset myUser = transfer.get("user", userID) /><br /><br /><!-- Now, lets update the users first and last name --><br /><cfset myUser.setfName("Harry") /><br /><cfset myUser.setlName("Smith") /><br /><br /><!-- Now, save this change back to the database --><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="user" table="Users" decorator="some.path.to.a.cfc"><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!

3 comments

Layers upon layers - model, controllers, and views, oh my!

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:

<br /><cffunction name="getItemsByAuctionID" access="public" returntype="void" output="false"><br />   <cfargument name="event" type="any"><br />   <br />   <cfset var items = getTransferFacade().listByProperty("item", "auctionID", arguments.event.getValue("auctionID"), "sortOrder") /><br /><br />   <cfset arguments.event.setValue("items", 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("myURLorFormVar") /><br /><cfset arguments.event.setValue("myVariableName", myVariableValue) /><br />

From within your view, you access your variables like this:

<br /><cfset viewstate.setValue("pageTitle", "This is my title") /><br /><cfset myLocalVar = viewState.getValue("varNameFromEvent") /><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.

0 comments

Secure your Model-Glue XML files from prying eyes

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!

Read more...

0 comments

Using iText to compile multiple Tiff images into a PDF

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="writePdfFromTiffs" output="false" returntype="string" hint="This will output a .pdf file containing multiple tiff images"><br />    <cfargument name="pdfOutput" required="true" type="string" hint="Provide a full path to output your PDF too"><br />    <cfargument name="tiffList" required="true" type="string" hint="Provide a comma deliniated list of tiff images to include"><br /><br />    <!---// This code was modified from code provided by bryan@electricedgesystems.com, thanks a ton! //---><br /><br /> <!---// Declare local variables to keep everything clean //---><br /> <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 />    <!---// Opan file system I/O to write pdf too //---><br /><cfset PdfFile = createObject("java","java.io.FileOutputStream").init(arguments.pdfOutput)><br />    <!---// Init the text.document object //---><br /><cfset Document = createObject("java", "com.lowagie.text.Document").init()><br />    <!---// Create pagesize argument so I can set new page sizes //---><br /> <cfset PageSize = createObject("java", "com.lowagie.text.PageSize") /><br />    <!---// Init the text.image object //---><br /><cfset Image = createObject("java", "com.lowagie.text.Image")><br />    <!---// Create our default paragraph object to contain our images //---><br /><cfset Paragraph = createObject("java", "com.lowagie.text.Paragraph")><br />    <!---// not sure what this does, but it needs to be here //---><br /><cfset PdfContentByte = createObject("java", "com.lowagie.text.pdf.PdfContentByte")><br />    <!---// Create PDFWriter class //---><br /><cfset PdfWriter = createObject("java", "com.lowagie.text.pdf.PdfWriter")><br />    <!---// Create array to contain image //---><br /><cfset RandomAccessFileOrArray = createObject("java", "com.lowagie.text.pdf.RandomAccessFileOrArray")><br />    <!---// Load TIFF image handling //---><br /><cfset TiffImage = createObject("java", "com.lowagie.text.pdf.codec.TiffImage")><br />    <!---// Assign the page size //---><br /> <cfset document.setPageSize(PageSize.Letter) /><br />    <!---// Set page margins to all 10 //---><br /><cfset document.setMargins(10,10,10,10) /><br />    <!---// Create instance of writer //---><br /><cfset Writer = PdfWriter.getInstance(document, PdfFile)><br /><br />    <cftry><br />      <!---// Open document for writing //---><br />   <cfset document.open()><br />      <cfset cb = writer.getDirectContent()><br /><br />      <!---// Loop through list of files provided as an argument and add each to our pdf //---><br />   <cfloop list="#arguments.tiffList#" delimiters="," index="curFile"><br />         <!---// Check this file to make sure it is a Tiff //---><br />      <cfif right(curFile, 3) eq tif or right(curFile, 4) eq tiff><br /><br />            <!---// Catch - try to account for un-accessable files or 32 bpp tiffs<br />               32 bit tiffs not supported by iText //---><br />         <cftry><br /><br />               <!---// stuff file into memory //---><br />            <cfset ra = RandomAccessFileOrArray.init(curFile)><br /><br />               <!---// read file and determine number of pages in TIFF //---><br />            <cfset comps = TiffImage.getNumberOfPages(ra)><br /><br />               <!---// loop over number of pages and add each one to the PDF //---><br />            <cfloop index="i" from="1" to="#comps#"><br />                <cfset img = TiffImage.getTiffImage(ra,javacast("int",i))><br />                <cfset img.scaleToFit(592, 772)><br />                <cfset img.setAbsolutePosition(10,10)><br />                <cfset cb.addImage(img)><br /><br />                <!---// force new page after each image is added //---><br />             <cfset document.newPage()><br />               </cfloop><br /><br />               <cfcatch type="any"><br />                  <!--- Ignore, un-supported file type //---><br />            </cfcatch><br />            </cftry><br />     </cfif><br />    <!---// Close each file after a loop //---><br /> <cfset ra.close()><br />      </cfloop><br /><br />    <!---// close document, this will write the pdf to the filesystem //---><br />   <cfset document.close()><br /><br />    <!---// Return success //---><br /> <cfreturn Success /><br /><br />    <!---// Catch any errors and return failed //---><br /> <cfcatch type="any"><br />    <cfreturn Failed /><br />    </cfcatch><br />    </cftry><br />   </cffunction><br />

0 comments

Using Alagads image.cfc to write positioned text

I needed to generate invoices based on a template, with data at many different positions on the image, then send it directly to our printer. I wrote this helper function that accepts an image.cfc instance (one that already has my blank image loaded) and writes text to a specific X / Y location on the image. Check it out, and hope it helps someone!

<br />   <cffunction name="imgWriteText" output="false" hint="This is a sub method that will write text over an image in memory at a specific location, font, weight, and style." returntype="struct"><br />      <cfargument name="imageVar" required="yes" type="struct" hint="This is the variable name that contains our Image.cfc object with our blank invoice image already loaded."><br />      <cfargument name="text" required="yes" type="string" hint="This is the actual text to be written"><br />      <cfargument name="xpos" required="yes" type="numeric" hint="This is the X position we are going to write our text at"><br />      <cfargument name="ypos" required="yes" type="numeric" hint="This is the Y position we are going to write our text at"><br />      <cfargument name="type" required="no" default="System" type="string" hint="This is the type of font, either system or truetype"><br />      <cfargument name="font" required="no" default="Lucida Console" type="string" hint="If a system font is specified, this is the name of the font. If a truetype font is specified, provide the full path to the font."><br />      <cfargument name="size" required="no" default="40" type="numeric" hint="Font size to be written"><br />      <cfargument name="color" required="no" default="black" type="string" hint="Color of the font to be written - name format"><br /><br /><br />      <!---// Declare all local variables //---><br />   <cfset var myFont = /><br />      <cfset var myColor = /><br />      <cfset var myString = /><br /><br />      <cfsilent><br />         <!--- make sure we have something to write before we attempt to do so ---><br />         <cfif Len(arguments.text)><br />            <!--- create a font object ---><br />            <cfswitch expression="#arguments.type#"><br />               <cfcase value="system"><br />                  <cfset myFont = arguments.imageVar.loadSystemFont("#arguments.font#", #arguments.size#, "plain") /><br />               </cfcase><br />               <cfcase value="truetype"><br />                  <cfset myFont = arguments.imageVar.loadTTFFile("#arguments.font#", #arguments.size#, "plain") /><br />               </cfcase><br />            </cfswitch><br /><br />            <!--- create the color black ---><br />            <cfset myColor = arguments.imageVar.getColorByName("#arguments.color#") /><br /><br />            <!--- create a string to write into the image ---><br />            <cfset myString = arguments.imageVar.createString("#arguments.text#") /><br /><br />            <!---// set our strings font //---><br />         <cfset arguments.imageVar.setStringFont(myString, myFont) /><br /><br />            <!--- set font color ---><br />            <cfset arguments.imageVar.setStringForeground(myString, myColor) /><br /><br />            <!--- draw the text, at the specified X and Y coordinates ---><br />            <cfset arguments.imageVar.drawString(myString, #arguments.xpos#, #arguments.ypos#) /><br />         </cfif><br />      </cfsilent><br /><br />      <cfreturn arguments.imageVar /><br /><br />   </cffunction><br />

0 comments