ColdFusion 9 PDF Enhancements

Another of the less visible, but still cool features in ColdFusion 9 are the enhancements we’ve made to <cfpdf>. We’ve added the ability to:

  • Add headers/footers to existing PDFs
  • Create PDF packages
  • Selectively optimize PDF size
  • Extract text from PDFs
  • Extract images from PDFs
  • Create high quality thumbnails

Of these features, my personal favorites are optimization and extraction.

Optimization

PDFs can do a lot. Consequently, PDFs size can swell due to the presence of extra information, metadata, and embedded files. The optimize feature allows you to remove specific types of extras in order to selectively reduce the size of your PDF. But you can retain features that you need. When you take action=”optimize” the following options are open to you:

  • noattachments
  • nobookmarks
  • nocomments
  • nofonts
  • nojavascript
  • nolinks
  • nometadata
  • nothumbnails

Code looks like this:

As you can see, the code is pretty straightforward. I’ve seen reductions of 65-75% on PDF size when using all options.

Extraction

Yes, you can get at the text or embedded images of a PDF with ColdFusion 9.

Here’s the code to get at the text of a PDF:

That code will extract the text of a PDF to XML. The structure divides the content into pages, so you can quickly get at content on particular pages, etc.

You have a few options that I’m not showing though. You can get the content as just a string. You can selectively get page numbers. You can even get XY coordinates for all of the words in the document.

Getting images is similar; you plug in a PDF, and send the images to a directory:

You have options to prefix the images, and pick image formats

As you can see, the engineers added some cool functionality here.

Caching Enhancements in ColdFusion 9

One of the less mentioned aspects of ColdFusion 9 is the enhanced caching that was added by including ehcache under the covers.

This opens a number of possibilities including fragment caching:

The time was #DateFormat(Now(), "mmmm d, yyyy")#
#TimeFormat(Now(), "hh:mm:ss tt")#

The time is #DateFormat(Now(), "mmmm d, yyyy")#
#TimeFormat(Now(), "hh:mm:ss tt")#

In this code, the first <cfoutput> will always show the time from the first time it was called. The second <cfoutput> will show the time from the actual time the code is called. The 1 for timespan means that it will cache that value for a day.

But, we can also do dependent cached items, where the value of one of the contained variables has an impact on whether or not the cached item needs to be refreshed.

The minutes is #minutesVariable#

The time was #DateFormat(Now(), "mmmm d, yyyy")#
#TimeFormat(Now(), "hh:mm:ss tt")#

In the above code, assume that it is called at 12:03. For the next minute minutesVariable is going to equal 3. For each call where minutesVariable equals 3 the cache is used. However when the time rolls over to 12:04, minutesVariable will equal 4. This will trigger a refreshing of the cache with the new content being cached for the next minute.

In addition to fragments, I can also cache objects (but for easy of understanding, variables) See this code:

SELECT *
FROM Artists

I try and retrieve the query that I’ve given an id of “testQuery” from cache, if it’s not there, I call the query and cache it.

So those are three fairly straight forward examples of the new caching, but you can do much more with it, including invalidating objects, analyzing cache usage, and more.

 

 

 

TR ORM Generator Code for ColdFusion Builder

I’ve been demoing an extension I made for generating ORM code CFCs, views, controllers and services. It stopped working with the public beta of ColdFusion. I’ve updated it to work with the public beta. I’ve tweaked it in a few other places, but it’s by no means completely tested. But if you like it and have ideas, I’m open to allowing other authors in. (We’ll just have to change the name of the tool. )

Please note, this is not an official Adobe product. It’s just code that I’ve been using that I’m willing to share. There is an ORM generator included with ColdFusion Builder; this is just another alternative.

Terry Ryan ORM Jumpstart at RIAForge

Word Wrap in ColdFusion Builder

A number of people have commented on the lack of word or line wrapping in ColdFusion. I whined to Adam Lehman about it, and he set me straight.

You can find it in the preferences:

Preferences -> HTML -> Editors

Under Editors there is a toggle button for General/Advanced. Click “Advanced”

Option reads “Enable Word Wrap” It will require a restart of ColdFusion Builder.

 

We’re talking about perhaps seeing if we can’t make this more obvious.

RAD without Rules

Those of you that have heard me talk at User Group tour talks, or at yesterday’s Online ColdFusion Meetup have heard me use the phrase “RAD without Rules.” It’s been going through my mind ever since I started using ColdFusion Builder and ColdFusion 9 together.

You see, ColdFusion was built as a Rapid Application Development tool for the web and for many of us it was alone in that space. However, it would be disingenuous of me to not acknowledge that there are tools that have stolen the spotlight away from ColdFusion. For me, this release of ColdFusion is about getting that spotlight back.

I was thinking about the phrase “convention over configuration” which seems to be the prevailing philosophy behind other RAD tools, like Ruby on Rails, Grails, Zend, etc. To me it means, “Code the way we tell you to, and we’ll make it fast.” It’s hard to tell tone here, but I’m not trying to knock this. A lot of smart people have done some awesome work with this mindset.

However, it never really fit with me, both when I was using frameworks and when I was writing them. People almost always chafe at the conventions. People always think they themselves can do things better then someone else. Not just me, in this case, but the people I was trying to get to use conventions. Some of that thinking is misguided. Some of it is “Not Invented Here” thinking. But at the end of the day, you’re always going to be more productive using something you believe in, rather than something you’re somehow compelled to use.

This leads me to the features of ColdFusion 9 and ColdFusion Builder.

ColdFusion Builder comes with extensions that generate code for you. Want to quickly generate code for viewing information in your database? You can do that. Hate the code we generate? You can completely change it. It’s written in CFML, and completely visible/editable to you.

Want to quickly build a modern, responsive HTML UI? You can use our built in UI components. Want to hand-code your front end using a JavaScript framework? Here’s CFAjaxProxy and our JSON features from ColdFusion 8 for you.

Want to do your front end in Flex? You can have it faster. Want to use ColdFusion in Flex quickly? You can use Exposed Services.

Want to work with PDFs? You’ve had that. Want to work with Office files? Now you can do that too.

We’ve added Hibernate ORM to ColdFusion. Want to wire up an object model in ColdFusion, and just have the CFCs define the database? You can do that. Want to model an existing database ignoring its structure, and instead building proper objects regardless of underlying structure? Guess what? Doable. Want to just provide CRUD for your existing database without writing a lot of code? You can just leave your ORM CFCs blank, and we’ll take care of that for you.

Don’t like ORM? That’s fine, CFQuery isn’t going away. We’ve tweaked it a bit, to use the application.datasource by default. Also, the code generation tools we provide will generate CFQuery code for you instead of ORM code. Don’t like the code we generated… you should get the point by now.

The point being this: instead of saying “Code the way we tell you to and we’ll make it fast” ColdFusion is saying “Code the way you want, we’ll make it fast.” That is what I mean by RAD without Rules.”

 

Public Bug Trackers for ColdFusion and ColdFusion Builder

We’ve been promising this one for awhile, but today we deliver. We have released a public bug tracker for ColdFusion and ColdFusion Builder. Now you can track both your bug reports and enhancement requests. You will also be able to vote for other people’s bugs (or drum up support for yours.)

These will probably not be the final URLs for these trackers, but they’ll work in the meantime.

We’d also like to thank the following developers for working so hard on it:

Questions about ORM in ColdFusion 9

So the ColdFusion 9 public beta has been released, and now everyone can play with it. I’m excited to hear what the community as a whole has to say about it. One of my favorite features is ORM or Object Relational Mapping.

As I’ve been traveling around for the user group tour, I’ve heard a few questions about it, and I wanted to share these thoughts.

Are you forcing us to use ORM?

Absolutely not – cfquery and its related tags aren’t going away. ColdFusion is about making what you want to do easy. If you want to work with queries, work with queries–we’ve made it pretty easy, as I’ve said before. But a number of customers wanted to work with databases in an easier, object-oriented way. A lot of developer effort has gone into doing that with various ColdFusion Open Source projects. It makes sense then that we would strive to make this easy too. That’s “too” as in “also,” or “additionally,” or “alternatively.” Or in other words, if you think ORM might have value, use it; if not, keep working the way that works for you because you are not required to use it.

In fact, we were actually able to expand the features of cfquery when we added ORM. In order to use ORM you have to add a datasource to the This scope in your application.cfc. Well when you do that, any cfquery in that application without a datasource tag will use the application.datasource. Very cool.

Why do I have to set all of these properties? Can’t ColdFusion just look at the database and create an ORM object?

Yes it can. If you leave your CFC blank, ColdFusion will just map the table that you are pointing to, no questions asked. However, if you want to set any properties manually, you’ll have to set them all. So it’s good for simple prototyping, but if you need to do something more complex, you have to do the work yourself.

Why doesn’t ORM return ColdFusion queries?

Objects and tables don’t always match up. Queries are really good for exposing the results of a Select statement, but they aren’t designed to handle complex sets of data. (Which is different from saying they cannot handle results of complex SQL Select statements, because they can.)

Sometimes you’ve got complex relationships; sometimes you have tables that are set up for one purpose, but used for another; and sometimes you have multiple tables that really should be one object. Queries can certainly accommodate this, but ORM can often do it in a way that makes you more productive. What would be multiple queries that you have to manage and loop through to display using queries, becomes one object in ORM.

Now add to it that you can add business logic to these objects, things like calculations, display formatting, and combined properties… and ORM shows itself to be much more valuable than just another way of handling data.

Okay, and let’s say you REEEAAAAALLLLY want a query. Okay, you can run a function named EntityToQuery that will convert the results of an ORM operation to a query. (Provided that it’s a simple object, with no relationships or other funny business.) (Not valid in Australia, for people named Mark, with or without marsupial pouches.)

Where can I find out more about ORM in ColdFusion 9?

There are a few good blog posts and articles on the subject:

I’ll try to add them as I see them.

 

ColdFusion 9 and ColdFusion Builder Public Beta

That’s right, as of 12:01 EDT am Monday July 13th
ColdFusion 9 (Centaur) and ColdFusion Builder (Bolt) are available for public beta testing.

Please check them out at Adobe Labs.

Also I’m doing a presentation for the Online ColdFusion Meetup today. Obviously, since we’ve released the beta bits, I can talk about any feature of it publicly now. So come with questions, and an eye to see as much as I can fit into two hours.