CF Groovy Redux

I just got through significantly revamping CF Groovy so that it's CFC based, instead of all in the custom tags.  The custom tags remain, but now you can create and manage a CF Groovy runtime instance manually, rather than letting the tags do it for you.  This will greatly assist in production performance as the tag-based version recreated everything each request.  It's also a prerequisite for Hibernate support, as Hibernate spinup is non-trivial and needs to be avoided unless needed, even in development.

These changes are still in the Hibernate branch in Subversion, not the main trunk.  I don't plan on moving the new code back to the trunk until the Hibernate integration is complete.

CF Groovy Takes a Nap

After close to two weeks of struggling, I finally managed to deploy pure source to a CFML runtime (Railo, in this case), and get Groovy entities in and out of the database with Hibernate.  No compliation, no IDE, no development-mode server, just my Groovy source along with a hacked up CF Groovy.  This is very exciting for me, because while Groovy is cool and all, CF's dynamic nature has become a must have.

I don't have source to download yet, just a horribly hacky proof of concept, but here's what the user of the "framework" does.  First, create your entity:

package com.barneyb
import javax.persistence.*

@Entity
class Person {

  @Id
  @GeneratedValue
  Long id
  Long version
  String name
  Date dob

  def getAgeInSeconds() {
    (new Date().getTime() - dob.getTime()) / 1000
  }

  def getAgeInDays() {
    ageInSeconds / 86400
  }

  def getAgeInYears() {
    ageInDays / 365.249
  }

  String toString() {
    "$name is $ageInYears years ($ageInDays days) old"
  }

}

That's the same class as my initial CF Groovy demo used, except with the of JPA annotations added.  Because I'm binding to Hibernate, you can use any Hibernate-supported annotations, but I opted to stick with vanilla JPA.  Now we need our hibernate.cfg.xml, which is totally stock:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

  <session-factory>

    <property name="current_session_context_class">thread</property>
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <property name="show_sql">true</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dbname</property>
    <property name="hibernate.connection.username">username</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.hbm2ddl.auto">update</property>

    <mapping class="com.barneyb.Person" />

  </session-factory>

</hibernate-configuration>

You could also map your classes manually with XML, if you wanted, but for the sake of simplicitly, I've done it all with annotations.  You'll also notice the database connection information embedded directly in the file. This is far from ideal.  I'm hoping to extract it from a CFML DSN, but that might only be possible on Adobe ColdFusion (via the Admin API).  The last thing is the test script:

<g:script>
  import java.text.SimpleDateFormat

  import org.hibernate.*
  import org.hibernate.cfg.*

  import com.barneyb.Person

  sdf = new java.text.SimpleDateFormat("yyy/MM/dd")
  sdf.lenient = true

  def sf = new AnnotationConfiguration()
      .configure().buildSessionFactory()
  def sess = sf.openSession()
  def tx  = sess.beginTransaction()
  sess.createQuery("delete Person").executeUpdate()
  sess.save(new Person(
    name: attributes.name ?: "Barney",
    dob: sdf.parse(attributes.dob ?: "1980/06/10")
  ))
  tx.commit()
  sess.close()
  sf.close()
</g:script>

No need to compile anything, no need to drop JARs all over your server, nothing.  Write, refresh, persist.  That includes adding new entities, new properties to existing entities, etc.

It's not ready for public consumption at the moment, but that's my top "free time" priority.  For the incredibly impatient, there's a branch in my SVN repository with the current source.  Don't expect anything pretty.  ;)

Railo 3 Beta 2

Railo dropped a second beta last night. Get it here. They've also added a WAR download, though it only works when installed into an existing "express" installation. Hopefully that'll get addressed for the next release.

A couple shining points about the runtime:

  • Array and Struct literals (the [...] and {…} notation) are expressions, exactly as they should be, unlike other CFML runtimes (cough…Coldfusion…cough).
  • Arrays and Structs now implement java.util.List and java.util.Map respectively, greatly easing Java integration. This also allows the Comparators CF Groovy example I published to work correctly on Railo.

Closures for Java

Wanting some light reading for this evening, I decided to dig into the Closures for Java draft spec (homepage).

Oh. My. God.

I'm a huge fan of closures. They're elegant, simple, and easy to use. Their semantics are subtle, but not confusing. They allow for very concise implementation of otherwise complicated algorithms, trimming a vast number of "normal" control structures, particularly various looping constructs.

Java already has (anonymous) inner classes which provide similar semantics, though with a marginally clunkier interface. This mechanism is basically how closures in Groovy are implemented, with some compiler magic to do the heavy lifting.

If you go look through the Closures for Java spec, however, what you see is appalling. Closures are about simplicity and elegance, and the spec outlines exactly the opposite. Closures themselves are exactly what you'd expect, using the Groovy (or Ruby) syntax, though types are required for the arguments. But what you don't expect is the function type syntax, the closure conversion rules, generics support, etc. It's a mess. Check this example:

String name;
{int => long} transform;

The first line declares a variable of type "java.lang.String". The second declares a variable of type "function that takes one int argument and returns a long". Note that that is different from a variable declared as "{int => int}", of course. Even better, any closure that can be assigned to the 'transform' variable implicitly implements every single-method interface whose method accepts an int and returns a long. It's unclear to me whether the converse is true - I couldn't take any more dry spec-speak.

The spec is pretty short (less than nine pages), and if you do any Java, it's definitely worth perusing. After reading, you'll realize that anonymous inner classes are just fine, thank you very much, even with the requirement of having to declare the interfaces explicitly. With the amount of baggage they seem to be lugging into Java (mostly because of it's typing), all I can say is "yuck." Closures require a bit more dynamic an environment to be effective, I think, and Java is static. Totally static.

ActionScript 3 provides an interesting middle ground that provides the benefits but culls a lot of the garbage. In AS3 you declare functions with typed arguments and an explicit return type. However, every function is of type function, which means if I have an algorithm that requires an {T, T => int} closure (that's the Comparator interface, by the way), I can happily pass in any old function I want and the compiler won't care. I'll get an error at runtime, of course.

Much the dancing the spec details is to protect developers from this potential situation, and the rest is to deal with backwards compatibility an interoperability with older libraries. I understand that Java is a strongly typed language, and that the compiler is omnipotent, but c'mon. Backwards compatibility is also very useful, but again, to what extent. You can already thrash a generics-based library with reflection, because it's absolved from compiler checks. It seems like there should be a point where you recognize the fact that the language has very deliberately poked holes in it's own security structures, and realize that that means trying to create airtight compiler checking is pointless.

I guess that's why Groovy got created, though. Backwards compatibility is important for Groovy as well, but the compiler (javac, mind you, not groovyc) and all it's type checking wonder has basically been given the finger since everything is just an Object and duck-typed as needed. Quack! I'm a developer that likes transparency in my compiler. Compiler writers are supposed to be smart, they can figure out what I'm doing and tell me if it'll work or not. I shouldn't have to give them explicit instructions, at least not that explicit.

NB: Function pointers (a la CFML) are NOT closures. Closures bind to their definition scope, function pointers just point at a function with no bound scope. I've heard the argument that function pointers are equivalent/sufficient. They're not.

Query/Reporting DSL Bug Fix

Rob Pilic found a couple local variables that I (gasp!) forgot to var scope in the DSL implementations while he was troubleshooting some concurrency issues.  There was one in each file, though totally unrelated.  I've applied his patch to Subversion and updated the demo install (though it won't matter, because it doesn't share instances).

Licensing My Code

I occasionally get questions about licensing my code for inclusion in other projects.  I thought I'd make a blanket statement that all my code can be assumed under the Apache 2 license unless otherwise indicated.  For where it's not explicit, just drop me a line if you need formal licensing, and I'd be happy to set it up.  Most of what I do is rather informally released (i.e. put in public Subversion), so I usually don't take the time.

Railo fixes Arrays and Structs

I just got a JIRA notice that Michael fixed Railo so that arrays and structs implement java.util.List and java.util.Map respectively. This is great news, because it means it's now possible to pass nested arrays and structs to Java APIs without having to manually rewrap them. From the ticket, it looks like the fix will be available in the next 3.0 beta, though I don't know when that's due out.

On the compatibility front, this means that the three major Java-based CFML runtimes (ColdFusion, Railo, and Open BlueDragon) all have compatible arrays and structs, which is a good thing if you need to write portable code that leverages underlying Java APIs.

CFML and Groovy

So As I said in my last post, there's been a lot of talk about integrating CFML apps with other bits.  I've been playing with Groovy and Grails a fair amount (duh), as well has having a lot of conversations about it.  I've been trying to figure out what the best use case is for the different pieces, and here are what I see as the main alternatives:

  1. Use Grails for your whole app stack
  2. Use Grails for your lower stack, and CFML for the view implementation (instead of GST).
  3. Use CFML for your web layer, and Groovy (maybe via Grails, maybe via plain Spring) for the lower layers, including GORM/Hibernate for persistence
  4. Use CFML for the web and service layers, and using Groovy w/ GORM/Hibernate for the data layer.
  5. Use CFML for the whole thing, and just stick in a bit of Groovy as needed, maybe with a partially GORM/Hibernate-persisted data model.

So what's the right one?  My initial feeling was option three, but after a bunch more talking and thinking, I'm now leaning towards number 4.  The service layer doesn't suffer from the same performance issues related to CFC instantiation that the data layer does.  So using CFML (w/ ColdSpring) has few real downsides for the service layer, but it has definite upsides because you can use CFML within the layer.  Better, you still get the huge benefit of Hibernate and POJOs in the data layer, which is where CF really has a lot of problems.

Interesting times to be sure.  Hopefully when I get back from the conference I'll have more time to write some code and really dig in.

CFUNITED Day One

As is typically the case, CFUNITED has a pair of themes.  There's the conference theme, which, as always, is helping CF coders become more empowered by learning about new things (OO, using CFCs, learning frameworks, etc.), and then there's the "backtheme".  This year it's all don't use only CF.  Adobe's integrating Hibernate into CF9, Railo is preaching the benefits of the JBoss platform (clustering, caching, Hibernate, etc.), Groovy has a lot of lovers, and Grails (which is Spring and Hibernate for Groovy) does to.

The integration of Hibernate all over the place is very exciting.  CF-based ORM tools suck, frankly.  Which isn't to belittle Mark or Doug in any way, they've done a fantastic job, it's problems with CF itself that are the issue.  With Railo's "CFC is a class" implementation, Hibernate is directly applicable.  With CF's crazy "a CFC is a bunch of classes in a Map" implementation, I'm not sure how Adobe's going to get it to work.  I'm very much hoping they fix the core issue (which would almost certainly give some nice performance benefits as well) instead of bastardizing Hibernate to get it to work, but we'll see.

Summer….

Here I am just out of the shower, sitting on the back patio with bare feet and a t-shirt, sunset behind the trees, listening to the babbling fountain and some Leaves Eyes', and finishing up a bag of Mother's Circus Animal cookies.  If only I had a fruity drink with a little umbrella in it…