Railo And AOP Transactions

If you're reading this, chances are good you're a software developer.  And that means you never touch the DB outside a transaction, right?  Of course, right.

Most of the time, transactions are a bit of a bear because their use is orthagonal to your business tasks.  To put that another way, business operations flow vertically from UI to backend to UI, and the various operations in your app typically flow mostly in separate parallel channels.  Transactions go across your application's structure, needing to be uniformly applied to all those operations, but being independent of all of them.  The "right" term for this is a "cross-cutting concern."

Fortunately, there are a pile of people in this world who are way smarter than I, and they've come up with Aspect Oriented Programming as a way to deal with these cross-cutting concerns.  The typical example shown is with logging, but transaction management is rather more useful, I think, isn't any more complicated, and is also more specific to AOP (whereas logging could be done with event-driven programming as well).  I'm not going to go into AOP, but if you're not using it, you should spend the time to learn a bit about it.  Really.

So the idea is to leverage AOP to automatically wrap your business methods with transactions.  In the CFML world, that means ColdSpring and its AOP support (which is modelled after Java's Spring framework).  Unfortunately, that's the easy part.  Since CFML servers abstract away DB connections (behind DSNs), it's hard to get ahold of the proper context to do the transaction demarcation correctly from your application code.  Somehow you have to know what the engine is doing behind the scenes so you can start/stop transactions at the right places.

When I wrote transactionadvice.cfc many years ago, I used a psuedo-ThreadLocal for tracking transactional method depth.  That way it can apply transactions at the top level, but skip them lower (nested) levels.  It works, but it doesn't handle multithreaded requests (i.e., using CFTHREAD) correctly, so it's far from ideal.  Using a real ThreadLocal would be better, but it requires Java or Groovy, and that's a dependency I don't want to require.  But for the majority of cases, it works fine.

Today, however, I discovered that Railo has this method:

getPageContext().getDataSourceManager().isAutoCommit()

It will tell you whether you're currently in autocommit (non-transaction) mode.  With this direct check of the transactional status, all the issues simply vanish, and the advice can be whittled down to this:

<cfcomponent extends="coldspring.aop.MethodInterceptor">

  <cffunction name="invokeMethod" access="public" output="false" returntype="any">
    <cfargument name="methodInvocation" type="coldspring.aop.MethodInvocation" required="true" />
    <cfif getPageContext().getDataSourceManager().isAutoCommit()>
      <cftransaction>
        <cfreturn methodInvocation.proceed() />
      </cftransaction>
    <cfelse>
      <cfreturn methodInvocation.proceed() />
    </cfif>
  </cffunction>

</cfcomponent>

Copiously excellent, if you ask me.  About the only thing that would make it better is if CFML grew a isAutoCommit() or isInTransaction() method so you don't have to dig into the underlying Java bits in an engine-specific way.

Tokenless location() Without Parameters

Both Railo and ColdFusion have added a builtin 'location' function in recent versions, and like their CFLOCATION counterpart, the default behaviour is to append the jsessionid/CFIDE/CFTOKEN tuple to the URL when redirecting.  I find this rather annoying, and it's even worse since FB3lite has a 'location' function which defaults it to false.  Unfortunately there isn't a way to use the FB3lite UDF in place of the engine built-in, so when you upgrade the server under a FB3lite app, suddenly the way your redirects work changes.

Fortunately, Railo implements the 'location' function as a CFML template, so you can easily go change the default.  If you install the WAR version the template is here:

/WEB-INF/lib/railo-server/context/library/function/location.cfm

If you install the bundled version, the 'railo-server' directory will be outside the webroot, typically here (thanks Todd):

{installation-dir}/railo/railo-server/context/library/function/location.cfm

Changing this file requires restarting your Railo webapp as the files are loaded once on startup.  As you'll quickly notice, there are a bunch of functions and tags that are implemented this way, so you can easily modify any or all of them to customize your environment.  Just be careful when you upgrade your Railo, as your changes will be overwritten.

Amazon S3 CFC Update – Now With Listings!

I've added two new methods to my Amazon S3 CFC: listBuckets and listObjects.  Both of them do about what you'd expect, returning a CFDIRECTORY-esque recordset object containing the rows you are interested in.  I've attempted to make S3 appear like a "normal" filesystem where "/" is S3 itself, the top-level directories are your buckets, and your objects are below that.  At the moment no consideration is made for paging or truncation.  Leveraging the new functionality, here's complete source for a simple S3 browser (minus your key/secret):

<cfparam name="url.path" default="" />

<cfset s3 = createObject("component", "amazons3").init(
  "YOUR_AWS_KEY",
  "YOUR_AWS_SECRET"
) />

<cfoutput>
<cfset bp = "" />
<h1>
<a href="?path=#bp#">ROOT</a>
<cfloop list="#url.path#" index="segment" delimiters="/">
  <cfset bp = listAppend(bp, segment, "/") />
  / <a href="?path=#bp#">#segment#</a>
</cfloop>
</h1>

<cfif url.path EQ "">
  <cfset b = s3.listBuckets() />
  <ul>
    <cfloop query="b">
      <li><a href="?path=/#name#">#name#/</a> #dateLastModified#</li>
    </cfloop>
  </ul>
<cfelse>
  <cfset q = s3.listObjects(listFirst(url.path, '/'), listRest(url.path, '/')) />
  <ul>
    <li><a href="?path=#reverse(listRest(reverse(url.path), '/'))#">..</a></li>
    <cfloop query="q">
      <li>
      <cfif type EQ "dir">
        <a href="?path=#listAppend(directory, name, '/')#">#name#/</a>
      <cfelse>
        <a href="#s3.s3Url(bucket, objectKey)#">#name#</a>
      </cfif>
      </li>
    </cfloop>
  </ul>
</cfif>
</cfoutput>

The default mode of operation assumes a delimiter of '/' (just like a filesystem).  If you want to do non-delimited operations (like generic prefix matching), you'll want to supply an empty delimiter, or you'll get weird results.  For example:

<cfset k_objects = s3.listObjects('my-bucket', 'k', '') />

If you omit the third parameter, the default 'k' will be used, and you'll get back objects within the 'k' psuedo-directory, rather than objects that begin with a 'k'.  This is the reverse of the default position of the raw S3 API, which assumes you want simple prefixing and makes you explicitly add the delimiter if you want psuedo-directory contents.

This dichotomy can also lead to weird results in the resulting recordset.  Every recordset comes with both 'bucket' and 'objectKey' columns that match the raw S3 nomenclature and 'directory' and 'name' columns that match the filesystem "view" of S3.  If you're doing raw prefixes you'll want to use bucket/objectKey (as the directory/name semantic doesn't work with prefixes).  If you're doing filesystem type stuff you'll probably want directory/name (though bucket/objectKey will still be correct).

Groovy Gravity Processing

Joshua (a coworker) and I have been talking about gravity simulation for a while, and this week I threw together a very simple model to do exactly that.  This grew out of a game called Flotilla that he came across somewhere and has been working with the developer to add a network multiplayer mode.  Flotilla, however, doesn't have a concept of gravity, and doesn't really have an explicit concept of mass either, except the implicit stuff in it's acceleration constraints.

Gravity, however, is kind of nasty to work with (from a computational perspective), particularly in a game situation (where you want realism, but not so real the game play sucks).  Fortunately, it's also exactly the kind of thing that I enjoy wasting my free time playing with.  So I threw together a simple model in Groovy, including a little type system and DSL to help keep my numbers straight.

So now when I divide a Force by a Mass, I'll get an Acceleration back.  Or if I multiply an Acceleration by a Time, I'll get a Velocity.  This was a huge win.  In the world of paper calculations, you don't do just arithmetic, you do unit algebra as well, which helps you ensure your answer makes sense (e.g., if you solve for velocity and get units of "meters per kilogram second", you screwed up somewhere).  But with a computer you don't have units, so I employed a simple type system to afford the same check I'd usually get from unit algebra.  And Groovy makes it remarkably easy to create both an expressive type system and a simple syntax (via operator overloading).

Then I hacked up Processing ever so slightly so I could implement a PApplet in Groovy and avoid the compilation step, and built a simple viewer for the model.  Emphasis on "simple".  Here's a capture with three bodies:

The bodies' sizes represent their relative mass, the green lines represent gravitation between them, the red lines are the velocity vector (per body), and the pink lines are acceleration (also per body).  Here's a few seconds later in the same simulation:

Now, because the bodies are far closer, the forces between them are much greater, which is going to result in a couple fairly impressive slingshots in a moment.  They've also picked up a fair amount of speed, though their active acceleration has surpassed their velocities (i.e., slingshots are imminent).  Here's after the slingshots have happened:

After the two larger bodies slingshotted around each other, the two smaller bodies did the same thing, resulting in a rapidly expanding model.  As you can see the forces are falling away, though the smallest and largest bodies will soon meet up and cross paths.  The velocity of the little one is high enough that the big one can't slow it down enough to do more than deflect it upward a bit.

Processing again completely delivered on it's promise of providing a remarkably simple way to sketch out visual stuff.  Simple event handling, simple setup, a simple draw loop, and solid primitives.  I need to do a little mucking about, but adding 3D support (which the model handles, but the viewer doesn't) will be similarly trivial: flip the "use 3D" bit, and add 'z' coordinates from the model in the various calls.  Very nice, especially when coupled with the Groovy syntax and capabilities.

An interesting project, though we'll see how generally useful.  Code, of course, is available from SVN.  It's a single Eclipse project, including Groovy, Processing, the hacked PApplet (from Processing), the model and the viewer applet.  Check it out and run driver.groovy to see it in action.  While running SPACE will pause/unpause the action, though there is currently no way to rewind/reset the simulation.  If you don't want to check out the project, you can browse it directly.  The interesting bits are in the /src/com/barneyb/gravity/ package.

Tulsa CFUG Presentation (CFGroovy)

Yesterday I presented CFGroovy to the Tulsa CFUG via Connect.  The recording is now available on Connect, thanks to Steve.  You can also grab the slidedeck (as a PDF) I skimmed through, and of course, the CFGroovy framework itself (project page, core SVN, demo SVN), including the demo files that I showed.  Note that the slidedeck is actually titled 'Polyglot Programming' and served as an introduction as to why you might want to use Groovy (or another language) before delving into how you'd actually do it.

Groovy DataSources for Railo

If you've ever wanted to do raw JDBC stuff in your ColdFusion applications, you probably know that you can get a javax.sql.DataSource via this code:

createObject("java", "coldfusion.server.ServiceFactory")
  .dataSourceService.getDatasource("myDSN")

Unfortunately, this doesn't work on Railo, because the result isn't actually a javax.sql.DataSource, it just looks like one (see RAILO-43).  To put that another way, it's duck typed.

Fortunately, Groovy's "fake" interfaces make beating the typechecks fairly trivial (if kind of ugly):



  def rds = variables.my.datasource
  variables.my.datasource = {
    rds.getConnection()
  } as javax.sql.DataSource

The CFSET gets the "datasource" as normal, and then the little Groovy scriptlet simply wraps it with a closure and tells it to pretend to be a javax.sql.DataSource. The game Escape from Tarkov has one important feature: after your death in a RAID, you lose your equipment. To prevent the loss of important equipment in the game, there are special sites with eft roubles you can always get top equipment and kill all pepegas squad. The items you store from needmana will not disappear. There are three types of containers in total. Alpha, Beta, and Gamma. These containers differ in their size. Usually, these containers should store the most important equipment-maps, ammunition, keys, and so on.  In this case we're assuming that the only method on DataSource that will be invoked is getConnection(), which is the usual case.  If you need to support other methods you'd need to go the Map-as-interface route.

Now we can use variables.my.datasource as a javax.sql.DataSource.  Yay!  Unfortunately, you have to use this sort of snippet everywhere you need a DataSource in your Railo apps, but hopefully that'll get fixed.

For more info on Groovy interfaces, the docs are at http://groovy.codehaus.org/Groovy+way+to+implement+interfaces.

CFGroovy at the Tulsa CFUG on May 25th

Next Tuesday (May 25th), I will be presenting CFGroovy to the Tulsa CFUG via Connect.  Details are at http://www.tulsacfug.org/meetings.cfm, but the important bit is that it's at 12:30 central time, not in the evening.  Steve Bryant – who manages the group – graciously extended a general invitation to anyone else who would like to join via Connect.  I'll post again with more details as we get closer to the event.

Do You Know These Shoes?

If you can identify this pair of shoes, I'll buy you a drink of your choice next time we meet.  If you're wearing a pair of them, I'll buy you two.

Red Shoes

GalConvict

This morning, in response to my Processing and Galcon post, I received this email:

Hey,

Stumbled across your article about using processing :)  Sounds neat!

Anyway, I don't like having to make these requests – but because of how
trademark stuff works I have to request that you change the name of your
project to something that doesn't contain the name Galcon.  Maybe
"PlanetConvict" or something like that.

Anyway, I'd really appreciate if you could do that :)

Thanks!
-Phil

As such, as soon as I can find a way to delete the GitHub repo – if you know how, please share – the code will vanish from the public view.  If you're interested in the bits, get 'em quick, or just email me.

Wheeee………….

Processing and Galcon

I did a little experiment last night using Processing, which is a Java-based visual programming environment that I've repeatedly run into in various different contexts, but had never really done anything with.  I've become completely addicted to Galcon Lite on my iPhone, and figured it was a "sample" to build with Processing.  Note that I was not attempting to replicate the look and feel of the game, just the mechanics.  If you don't know Galcon, here's a screenshot:

The basic idea is that you take over planets (which produce more ships), and try to exterminate your opponent (which I'm moments away from doing).  The green planets are mine, the grey planets are neutral, and the orange is my opponent.  Here's a similar just-about-to-win screencapture from my version of the game:

Rather than have masses of ship icons, I grouped them into fleets (the hollow circles) with the number of ships indicated.  Notice that I also don't make my fleets go around other planets, as evidenced by the "26″ fleet going through the "19″ planet right in the middle.  Gameplay, however, is basically identical to the original.

I made the code available on GitHub: http://github.com/barneyb/GalConvict. It's hardly the Mona Lisa.  I made exactly zero effort to architect, refactor, etc.  It was just a proof of concept for playing with Processing. [2010-05-17: This has been retracted - read why]