Archive for the 'groovy' Category

CF Groovy w/ Hibernate Sample App

I want to put together a little sample app leveraging CF Groovy and it's Hibernate integration, but I don't know what. From a high level, the architecture will look like this:

  • CFML for the view layer (the HTML templates)
  • CFML for the web controller (probably FB3Lite)
  • CFML and Groovy for the service layer (ColdSpring-managed CFC's with Groovy delegation where appropriate)
  • Groovy w/ Hibernate for the data layer

The question is what the application should do. The default choice of a simple blog engine is, well, boring. I considered implementing the BlogCFC API as a drop-in replacement for BlogCFC backed by Hibernate, but that means mapping the legacy schema, which I don't really want to get into for a simple demo.

My next choice is a simple survey application, since that at least has the potential to be real-world useful. It's also sufficiently simple and would provide appropriate illustration of the concepts I need to demo. The data model for survey construction is simple, but it gets a bit nastier with response storage, and I'd like to avoid too much nasty.

I've implemented a basic timeclock as a sample app a few times (CFML, Spring+Hibernate, Grails) as well, but there's a lot of "application" in there, compared to the amount of persistence, which is what I want to be highlighting.

So, my all-knowing readers, what simple app do you want me to implement? Preferably something that will be useful to people, either as it is, or as a starting point for building a richer version of what I produce. I've just about got the Hibernate APIs nailed down, but I've got a couple more hours on that task.  I'm thinking that Wednesday night I'll pick something and start coding, so speak up (in the comments) with what you want to see.

Fun with Classloading in Java

With my CF Groovy project, I've been doing a lot of Java coding of late. It's all been written in CFML, but it's mostly Java code in CFML syntax. As an aside, doing that sucks. CFML is horrible for writing anything more than the simplest Java code. But on to the topic at hand….

To this point in my career, basically all of the Java code I've written has been application code. Most of the CFML, JavaScript, and ActionScript I write is also application code, but I've contributed significantly to Fusebox and built a number of micro-frameworks in all three languages. However, none of that touches on the stuff I've done in the past couple weeks. The primary source of my issues getting Groovy and Hibernate to play together was classloading.

Unlike Grails (GORM, really), any of the various examples on the web, and I'm guessing Joe Rinehart's Hiberailooving project, three of the inviolate framework objectives were zero dependency on an IDE beyond text editing, no manual compilation, and no container restarts. Obviously, Hibernate provides a set of IDE tooling that can be brought to bear, but I'm talking about just the CF integration portion. I want to be productive with emacs and a web browser.

This presented a number of issues with classloading, because Groovy can only be loaded by the GroovyClassLoader (and subclasses). Basically this forced my hand to using compiled Groovy code, and ensuring it and Hibernate are loaded by the same ClassLoader. No GroovyClassLoader at all.

Now all that's well and good, but you have to be a bit careful, because two of the goals where no manual compilation and no container restarts. Doing compilation from CF is fairly simple (instantiate FileSystemCompiler and call 'main' with the right args), though again, getting all the right stuff on the classpath in the right order proved a nightmare. This is further complicated by the while JEE classloader situation, which isn't straightforward at all.

The details of this intricate dance completely escaped me for a week and a half. Then one night, while lying in bed, it all clicked together (thank you, Heather, for going to England). The solutions seem fairly obvious now, but they took a lot of fussing and fighting to deduce. I'd never even instantiated a ClassLoader before, aside from a couple one-off URLClassLoaders in CFML to lazy-load some JARs. Now I've got stacks of ClassLoaders, in some places two or three deep.

After my initial post-epiphany implementation was complete, I realized I can do some streamlining, but that's for after the release. I think I can even remove the need to drop the Groovy JAR in your /WEB-INF/lib folder, without adding any code complexity or runtime overhead, which would a nice bonus for ease of deployment. I.e., unzip the engine, write an entity, save it to the DB. No JARs, no restart the container, nothing.

It's been a very interesting (and pleasurable) experience, since it's so different from my day job of banging out boring little presentation apps all day. I've learned a lot, and even just the past few days of thinking about how other Java apps/frameworks work, I've realized how applicable that knowledge really is.

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.  ;)

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.

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.

Scriptlets in CF Anyone?

My last post about Comparators via CF Groovy was simplistic in nature, but the underlying concept is incredibly powerful.  Here's a similar snippet (from the demo app), this time using a Comparator class:

<g:script>
Collections.sort(variables.a, new ReverseDateKeyComparator())
</g:script>

So what do we have here?  Why it's a snippet of Java embedded directly in your CFML page, and it gets dynamically compiled and executed just like the CFML.  Let me say that again: it's a snippet of Java embedded directly in your CFML page.  It's even better than that, though, because it's Groovy, which is Java plus a whole lot more.

In addition to the scriptlet functionality, CF Groovy provides a classloading framework for Groovy scripts and classes, in addition to the ones provided by the CFML runtime and the JVM.  You can define an extra Groovy classpath for your scriptlets like this:

<g:setPath path="#expandPath('/groovy')#,#expandPath('/packages')#" />

There's no way to tell how the ReverseDateKeyComparator class in the first example is implemented, but it happens to be a Groovy class that I've added to the classpath with the <g:setPath> tag.  That class, just like the scriptlet, is dynamically compiled and executed just like the CFML.  This is also very powerful, because it eliminates the compile/build/deploy cycle that is usually required for Java code in a JEE environment.

Combining these two, you can use <g:script> to execute arbitrary scripts from the Groovy classpath, instead of inlining them:

<g:script name="myScript.groovy" />

This lets you reuse scripts across CFML pages, as well as reusing classes between scripts.

I've added CF Groovy to my Projects page, so that's the place for the latest info, as well as some documentation and the all-important Subversion information.

Comparators in CF with Groovy

I don't know about anyone else, but wanting to create little ad hoc Java classes in my CF apps in a common occurrence for me.  With my CF Groovy project, it's both possible and very easy.  No Java, no compiling, no classloading hacks.

Here's a simple example.  I'm going to create an array of structs and then sort the array based on a specific field value (the 'date' field) of the structs.  Doing this in CF usually means making a lookup struct, sorting that, and then rebuilding the array (but only if you have unique values), or converting to a query and using QofQ to do it.  Both have serious drawbacks, as well as being very circuitous/obscuring.

First the array construction (six items, each with 'letter' and 'date' fields, holding what you'd expect).  Nothing very interesting here.

<cfscript>
a = [];
month = createDate(year(now()), month(now()), 1);
for (i = 1; i LTE 6; i = i + 1) {
    s = {
        letter = chr(65 + randRange(0, 25)),
        date = dateAdd("d", randRange(0, 30), month)
    };
    arrayAppend(a, s);
}
</cfscript>

Now, using the <g:script> tag from CF Groovy, we'll sort it by date using a java.util.Comparator:

<g:script>
Collections.sort(variables.a, {o1, o2 ->
    o1.date.compareTo(o2.date)
} as Comparator)
</g:script>

If you want to compare based on the letter, just change the two ".date" references to ".letter".  You can, of course, make the comparator as complicated as you'd like, including referencing other Groovy classes through CF Groovy's classloading, or other Java classes on your classpath.

You can see it in action at the demo page, or get the full source from Subversion at https://ssl.barneyb.com/svn/barneyb/cfgroovy/trunk/demo/.

CF Groovy

Those of you who remember CF Rhino will recognize the name for my latest little project. I whipped up a small proof-of-concept integration for Groovy into CF apps tonight while playing with some classloading issues within Groovy itself.

Groovy has a number of advantages for this type of integration of JavaScript, the biggest one being that Groovy IS Java, and carries Java's semantics almost perfectly. So unlike with Rhino, no major conversions are needed moving in and out of Groovy, which makes things enormously easier. CF still brings it's special blend of "insane" to the party, but it works quite well overall. Definitely has more real-world potential than CF Rhino ever did.

CF Groovy is not a whole framework like CF Rhino was, it's really just a proof of concept for integrating the two together and sharing resources. You can get the demo (which includes the engine via svn:externals) from Subversion at https://ssl.barneyb.com/svn/barneyb/cfgroovy/trunk/demo/. Just check it out to a directory named 'cfgroovy' in your webroot, drop the groovy JAR from the 'groovyEngine' subdirectory into your /WEB-INF/lib folder, and you should be done.  You can see it in action at the demo page, though without source to browse, it's not very interesting.

Also, unlike CF Rhino, there's no dependencies on the internals of ColdFusion (the Adobe product). To do some of the bridging to JavaScript, I had to invoke internal APIs of ColdFusion, so it wouldn't run on BlueDragon, Railo, etc. I built CF Groovy with Open BlueDragon and Railo 3 on Tomcat simply because I didn't have a CFML runtime on my box, and CF is like 400MB while oBD is 11MB and Railo is 25MB.

Unfortunately, all three runtimes have bugs that prevent them from working as expected.

Railo was the worst: it has some recursion issue with the JEE.include() call. It also doesn't seem to implement java.util.Map with it's struct implementation, and throws on missing keys rather than returning null.

Open BlueDragon initializes ResultSets from manually assembled queries (and possibly "real" queries) with the row pointer pointed at the first row, rather than before the first row as the spec says it should be.

ColdFusion doesn't create java.util.Date objects with the createDate built in, so trying to call ResultSet.getDate() throws a ClassCastException. Using ResultSet.getObject() and letting the ducks work their magic fixes this issue. It's also 15-35 times larger than the others.

Except for the download size issue, I've got conditionals to cover all the cases in the app, so it should be checkout and run on all three platforms. I haven't tested NA BD, CF7-, or Railo 2. I don't know why they wouldn't work, though, since I'm just doing standard Java stuff. I'm not doing any version conditionals, only platform ones, just in case.