FlexChart 2.0

I've released FlexChart 2.0 today.  Binary download is available here: flexchart_2-0-r4392.zip.  The demo app is still available, of course.  Backwards compatibility is not quite 100%, as I'll explain below, but the non-compatibilities only affect certain classes of charts, and they're the complex ones.  For simple stuff it should be drop-and-go.

There are no real outward changes to the engine.  It's still shipped as a SWF and with a CFML demo app and custom tag.  It's loadable by SWFObject if you prefer that, and since it's interplay with the world is strictly via JavaScript and XML, it's totally application platform independent.  It's designed with Ajax in mind, as you might imagine, and fits into that realm very well.

Under the hood, however, you'll find all kinds of changes.  The first version was a proof-of-concept app that I build one Friday afternoon and then extended with a few more bits over time.  It did direct XML-to-UIComponent translation with no validation, no unit tests, and no debugging assitance.  It was also a huge pain to work with, because the inside all operated on either an XML DOM tree or a ChartBase instance, neither of which is fun to debug.

The new version is a four phase engine: parse, transform, validate, build.  Unifying them all is an intermediate representation that the parser creates, the transformer manipulates, the validator validates, and the builder uses to construct the ChartBase instance for actually adding to the stage.  There are FlexUnit unit tests for the first three phases, along with a couple for the builder phase.  I couldn't figure out how to test the builder reliably (because it's "output" is all UIComponents) until quite late in the process, so the coverage is only for a couple bugs that came up.

Because of the more explicit nature of the engine, error handling is far better.  Internal errors caused by improper descriptors are also caught and displayed to the user for easier debugging.  There is not currently a way to suppress this behaviour, maybe in a future version.

The rewrite also allowed me to hide some evilness lurking inside the Flex charting components.  In particular, if you've used grouped series and the grouped legend, you'll possibly need to revisit things a bit.  This is the one place where backwards compatibility was sacrificed, but the changes required in the XML are minor and a significant number of edge cases that the first engine couldn't handle are now dealt with correctly.  Note that these weren't really bugs in the first version, but rather limitations in the Flex charting components that the first version didn't hide away from the user.  I.e. in order to build certain charts you had to have an intimate understanding of the Flex charting components' internals.  That's been fixed.

Bugs, comments, and questions welcome as always.

Java SE 1.6.0_10

Just did the 1.6.0_10 upgrade on my server.  Oh how I love Linux.  Just unarchved the new JDK, repointed a single symlink and restarted my Java servers.  There didn't seem to be a significant difference in spinup time for my ColdSpring AOP-heavy apps – perhaps a touch faster.  No problems with Magnolia either as near as I've been able to tell.  WordPress, not surprisingly, was unaffected.

"Missing Huffman code" Error Using ImageWrite()

I've been having troubles with thumbnail generation on one of my apps recently.  Just sporadically, with no obvious pattern as to why.  The error is about a missing Huffman code (used for JPEG compression).  Turns out that certain images when being written at certain sizes, throw this error when you use the built-in imageWrite().

The solution is to skip the CF solution and manually do it the Java way.  So what used to be this:

<cfset imageWrite(image, filename) />

now looks like this:

<cfset createObject("java", "javax.imageio.ImageIO").write(
   imageGetBufferedImage(image),
   "jpeg",
   createObject("java", "java.io.File").init(filename)
) />

Fortunately, Adobe had the foresight to include the wonderfully named imageGetBufferedImage() built-in so you can access the raw image data with the native Java APIs.  Note that with the Java you have to specify the encoding type explicitly, instead of letting CF figure it out based on the filename's extension.  Since I'm only dealing with JPEG images, I just hard coded it.

Chrome and Google Spreadsheets

I use Google Spreadsheets for a few things (and other doc types for a few others), but I usually do hard-core editing in Excel.  Export from the web, edit in Excel (or more likely Calc), reimport into Docs.  Hardly elegant, but when I'm going to be cranking a workbook for two or three hours it's worth it compared to editing online.

I was getting set up to do just that this evening, and it occurred to me that the online experience probably doens't suck nearly as much in Chrome.  So I went and grabbed it, set it up with the latest dev build (instructions), and fired 'er up.

Much to my delight, it's actually quite good.  They also added a multi-line editor for cell values that you can resize as needed, which makes editing huge formulas way easier.  No more copying out of the Excel bar into TextPad to edit a formula and then copy it back in.  Still a few issues with keyboard navigation, but they seem to be bound to the fact that "type in the cell" and "edit the cell" are expressed in very similar ways, so you can't tell which mode you're in without thinking pretty hard.  I'm trying to figure out what's different with Excel (where I don't recall having this problem), but I can't put my finger on it.

Spreadsheet's filter function is also pretty slick.  Excel has roughly equivalent functionality in it's DB functions, but filter is way slick.  You don't have to define a database range, it just figures it out, and you don't need explicit criteria cell pairs, you express the filter clauses directly in the formula.  It took me a few minutes of struggling to figure out what the syntax really meant by the examples in the docs and how it applied to my problems, but it quickly became obvious once I willed the nasty Excel way out of my brain.

In any case, I think I'm done with the roundtripping via Excel.  With a kick-ass JS engine behind it, the online version is close enough to a real spreadsheet app.  Recomputing complex formulas is still slower than I could like, but that's about my only remaining complaint.  And no, I didn't do any actual comparative profiling, but again, I don't recall seeing significant lag with Excel when I've done complicated stuff on there.

More FlexChart Stuff

I've made another minor enhancement to FlexChart, this time around grouped legends.  Previously, if you mixed grouped series and ungrouped series (e.g. a stacked column chart with a line series overlaid), the legend would be all kinds of wonky for the line series.  I've fixed that so it'll now render in a reasonable way.

As always, the demo app (with a new preconfigured chart illustrating the functionality) is available at http://barneyb.com/flexchart/, including instructions for downloading both the source and the binaries.

I've also received a couple questions about cross-platform support.  There is absolutely nothing CFML specific about the component.  I happen to package a CF custom tag with the SWF, and the demo app is written in CFML, but the component itself only deals with the Flash Player and XML.  I've personally fed it XML with GroovyServlet and PHP, as well as ColdFusion and Railo.

CFGroovy Demo App Update

A couple users complained that my CF Groovy demo app doesn't work on MS SQL Server because Hibernate doesn't escape the table names it creates, and "user" is a reserved word.  Since I do all my work on MySQL, I never saw the issue.

I've updated the code to use an @Table annotation to specify an alternate table name ("user_t") to use, to alleviate the issue.  No other code changed.  If you update to the new code, your existing data will "disappear".  In reality, it doesn't disappear, Hibernate just created a new blank table with the new name.  If you want the old data back, just do a "insert into user_t select from User;" (or whatever the equivalent is), and then drop the "User" table.

As always, the demo is available at: http://barneyb.com/cfgroovy/, including instructions on how to get the latest code.

Backgrounder FTW

The iPhone has a number of problems, but the inability to background applications is one that just got fixed.  There's a new app on Cydia for backgrounding an arbitrary application, called surprisingly enough, Backgrounder.  It adds a couple behaviours to your home button for backgrounding, as well as supporting the ability configure apps to always background.

Obviously have to have a jailbroken phone to do it, but with QuickPwn it's a breeze.  Now you can listen to Pandora while you surf the web or check your email just like you can with the iPod app.  Or stay signed into chat while you go look up a contact.  Now if only they'd fix copy and paste, attaching images to emails, text selection, etc.

Application.cfc Mappings Gotcha

If you use Application.cfc mappings on Adobe CF, watch out.  If your mapping names contain only alphanumerics, the leading slash is optional.  However, if the name contains other characters (like an underscore), then you HAVE to use the leading slash or it won't resolve.  Ran into this on an app where my "coldspring" mapping worked flawlessly, but my "schema_tool" mapping refused to resolve.  Unfortunately for me, I wasn't aware that "coldspring" worked until about half an hour in to troubleshooting, because the "schema_tool" mapping gets used first.

The livedocs' example does not show leading slashes, which misled me for quite a while after I resorted to looking there when it didn't work.  It's been a long time since I went to livedocs, and I remember why.  ;)  If you scroll down, however, there is a comment about the leading slashes.  It's only five months old, so hopefully it'll get incorporated into the actual document at some point.

In the mean time, make sure you get those leading slashes in there!  I haven't tested this issue on any other CFML engines, but as long as you don't forget the slashes, it shouldn't matter.

FlexChart Update

Been a long while since I've made any updates to FlexChart, and this is only a minor one, but it's potentially important.  Since it's designed to be used in JavaScript applications, data tips and click events are all processed by JavaScript (not ActionScript).  When I'd created the data tip callbacks, I'd neglected to considered the hierarchical nature of sets of series.  So I've added a 'seriesContext' array that contains the context for the series that is having it's data tip generated.  This is strictly an additive change, the existing 'seriesLabel' remains, though it is present in the 'seriesContext' array as well.

What is this good for?  I need to create a funnel chart, and while the built-in stacked-column chart is close, it computes the percentages in the data tips the wrong way.  Reimplementation was a snap with the context, just pull the relevant numbers out of the descriptor XML and do the division.

Even More Groovy

I have a confession to make.  My neat little code counter utility is partially a lie.  I wrote the entire thing as a single Groovy script, and only split it up into individual files for each class to release it.  271 lines of code (419 if you count the blank lines) simply does not justify seven distinct files.  That said, it does justify a runner script and six distinct classes.  So if you want the "real" source, just take the six classes, copy them directly into Runner.groovy and then delete the files.  Everything works exactly the same, except it's all in one concise package.

The project started with a pile of procedural code (i.e. a Groovy script), all inline with no classes at all.  My basic concepts proved sound, and I started refactoring.  Does anyone NOT like refactoring?  If so, raise your hand so I'll know who to slap.  ;)  Classes quickly started falling out of the proof-of-concept code, and soon I had my four core classes (CodeCounter, ProjectInfo, PathInfo, and FileInfo), plus some no-longer-quite-functioning output code.

Once the "backend" was refactored into a stable model, the front-end went just the same.  XML was the format of the original script, and so I reimplemented the same output based on the model, rather than emitting it inline.  To ensure I wasn't being stupid and coupling where I shouldn't, I threw together the text renderer as well.

I'm a huge fan of this style of development, and do much the same thing with CF.  Start writing one big-ass file with no real concern for parameterization, abstraction, or encapsulation.  Once it works "enough", start refactoring for those three characteristics, as well as extending the functionality into something useful to the real world.

Doing Java is a bit harder, since you have the object nature foisted on you from the start.  You can still begin with one class and a pile of static methods, but the refactoring is a bit harder, I think, because of the static/dynamic transition.  With CF and Groovy, you pretty much bypass all of that (thank you compilers!), which is very nice.

What's the downside to this style of development?  Unit testing is hard.  With a rapidly evolving project (structurally), having to evolve unit tests can be a significant burden.  Not to mention that you can't really unit test a single large script; you're stuck waiting until you have an class which is after most of the work is done.  So if you write unit tests at all (I didn't), they have to come late in the cycle.

The main benefit is that you don't have to think about architecture before implementing functionality.  If you know exactly what your desired functionality is, and know how you're going to approach implementing it then architecture is the "hard" part, and unit tests can help ensure your implementation matches what you expect/require.  However, that's not the case a lot of time.